Javascript Async会等待在redux thunk函数中返回数据

Javascript Async会等待在redux thunk函数中返回数据,javascript,typescript,react-native,redux,redux-thunk,Javascript,Typescript,React Native,Redux,Redux Thunk,我一直在尝试用来自mongo db realm数据库的数据填充我的redux存储。 无论何时我运行下面的函数,它都会正常执行,但问题是数据会延迟,最终无法到达我的redux存储 我的thunk功能: export const addItemsTest = createAsyncThunk( "addItems", async (config: any) => { try { return await Realm.open(config).th

我一直在尝试用来自mongo db realm数据库的数据填充我的redux存储。 无论何时我运行下面的函数,它都会正常执行,但问题是数据会延迟,最终无法到达我的redux存储

我的thunk功能:

export const addItemsTest = createAsyncThunk(
  "addItems",
  async (config: any) => {
    try {
      return await Realm.open(config).then(async (projectRealm) => {
        let syncItems = await projectRealm.objects("Item");
        await syncItems.addListener((x, changes) => {
          x.map(async (b) => {
            console.log(b);
            return b;
          });
        });
      });
    } catch (error) {
      console.log(error);
      throw error;
    }
  }
);
还有我的redux减速机:

  extraReducers: (builder) => {
      builder.addCase(addItemsTest.fulfilled, (state, { payload }: any) => {
        try {
          console.log("from add Items");
          console.log(payload);
          state.push(payload);
        } catch (error) {
            console.log(error)
         }
      });
  }
预期结果: 我的redux存储应该有这些数据一次
addItemsTest
返回一些内容:

[{
itemCode: 1,
itemDescription: 'Soccer Ball',
itemPrice: '35',
partition: 'partitionValue',
},
{
itemCode: 2,
itemDescription: 'Base Ball',
itemPrice: '60',
partition: 'partitionValue',
}
]
实际结果:

混合语法 您将
await
/
async
Promise.then()
语法以一种非常混乱的方式组合在一起。混合使用这两种语法不是错误,但我不建议这样做。坚持使用just
wait
/
async

无效回报 您的操作实际上现在没有返回任何值,因为您的内部
then
函数没有返回任何值。唯一的
返回
内部,然后
x.map
回调中
wait syncItems
是映射器的返回值,而不是函数的返回值

现在,你的恶棍是这样做的:

  • 打开连接
  • 从域中获取项目
  • 向记录更改的项目添加侦听器
  • 返回一个
    承诺
    ,该承诺解析为
    无效
解决方案 我相信你想要的是:

export const addItemsTest = createAsyncThunk(
  "addItems",
  async (config: any) => {
    try {
      const projectRealm = await Realm.open(config);
      const syncItems = await projectRealm.objects("Item");
      console.log(syncItems);
      return syncItems;
    } catch (error) {
      console.log(error);
      throw error;
    }
  }
);
如果没有日志记录,可以简化为:

export const addItemsTest = createAsyncThunk(
  "addItems",
  async (config: any) => {
    const projectRealm = await Realm.open(config);
    return await projectRealm.objects("Item");
  }
);
您不需要捕获错误,因为
createAsyncThunk
将通过调度错误操作来处理错误

编辑:侦听更改 似乎您的目的是将redux存储与领域集合中的更改同步。因此,您希望向调用
dispatch
的集合添加一个侦听器,并执行一些操作来处理更改

在这里,我假设此操作使用包含集合中所有项的数组。大概是这样的:

const processItems = createAction("processItems", (items: Item[]) => ({
  payload: items
}));
替换您所在州的整个阵列是最简单的方法。当您用相同的版本替换项对象时,这将导致一些不必要的重新渲染,但这不是什么大问题

或者,您可以传递的特定属性,例如
插入
,并在reducer中逐个处理它们

为了添加分派
processItems
的侦听器,我们需要访问两个变量:realm
config
和redux
dispatch
。您可以在组件中或通过调用“init”操作来执行此操作。我认为没有太大区别。如果需要,您可以在reducer中对“init”操作做出响应

下面是一个添加侦听器的函数。
Realm.Results
对象是“类似数组”的,但不完全是数组,因此我们使用
[…x]
将其强制转换为数组

仅供参考,此函数可能会引发错误。如果在
createAsyncThunk
中使用,这是很好的,但是在组件中,我们希望
捕获这些错误

const loadCollection = async (config: Realm.Configuration, dispatch: Dispatch): Promise<void> => {
  const projectRealm = await Realm.open(config);
  const collection = await projectRealm.objects<Item>("Item");
  collection.addListener((x, changes) => {
    dispatch(processItems([...x]));
  });
}
直接添加侦听器:

const EffectComponent = ({config}: {config: Realm.Configuration}) => {
  const dispatch = useDispatch();

  useEffect( () => {
    // async action in a useEffect need to be defined and then called
    const addListener = async () => {
      try {
        loadCollection(config, dispatch);
      } catch (e) {
        console.error(e);
      }
    }

    addListener();
    
  }, [config, dispatch]);

  /* ... */
}
混合语法 您将
await
/
async
Promise.then()
语法以一种非常混乱的方式组合在一起。混合使用这两种语法不是错误,但我不建议这样做。坚持使用just
wait
/
async

无效回报 您的操作实际上现在没有返回任何值,因为您的内部
then
函数没有返回任何值。唯一的
返回
内部,然后
x.map
回调中
wait syncItems
是映射器的返回值,而不是函数的返回值

现在,你的恶棍是这样做的:

  • 打开连接
  • 从域中获取项目
  • 向记录更改的项目添加侦听器
  • 返回一个
    承诺
    ,该承诺解析为
    无效
解决方案 我相信你想要的是:

export const addItemsTest = createAsyncThunk(
  "addItems",
  async (config: any) => {
    try {
      const projectRealm = await Realm.open(config);
      const syncItems = await projectRealm.objects("Item");
      console.log(syncItems);
      return syncItems;
    } catch (error) {
      console.log(error);
      throw error;
    }
  }
);
如果没有日志记录,可以简化为:

export const addItemsTest = createAsyncThunk(
  "addItems",
  async (config: any) => {
    const projectRealm = await Realm.open(config);
    return await projectRealm.objects("Item");
  }
);
您不需要捕获错误,因为
createAsyncThunk
将通过调度错误操作来处理错误

编辑:侦听更改 似乎您的目的是将redux存储与领域集合中的更改同步。因此,您希望向调用
dispatch
的集合添加一个侦听器,并执行一些操作来处理更改

在这里,我假设此操作使用包含集合中所有项的数组。大概是这样的:

const processItems = createAction("processItems", (items: Item[]) => ({
  payload: items
}));
替换您所在州的整个阵列是最简单的方法。当您用相同的版本替换项对象时,这将导致一些不必要的重新渲染,但这不是什么大问题

或者,您可以传递的特定属性,例如
插入
,并在reducer中逐个处理它们

为了添加分派
processItems
的侦听器,我们需要访问两个变量:realm
config
和redux
dispatch
。您可以在组件中或通过调用“init”操作来执行此操作。我认为没有太大区别。如果需要,您可以在reducer中对“init”操作做出响应

下面是一个添加侦听器的函数。
Realm.Results
对象是“类似数组”的,但不完全是数组,因此我们使用
[…x]
将其强制转换为数组

仅供参考,此函数可能会引发错误。如果在
createAsyncThunk
中使用,这是很好的,但是在组件中,我们希望
捕获这些错误

const loadCollection = async (config: Realm.Configuration, dispatch: Dispatch): Promise<void> => {
  const projectRealm = await Realm.open(config);
  const collection = await projectRealm.objects<Item>("Item");
  collection.addListener((x, changes) => {
    dispatch(processItems([...x]));
  });
}
直接添加侦听器:

const EffectComponent = ({config}: {config: Realm.Configuration}) => {
  const dispatch = useDispatch();

  useEffect( () => {
    // async action in a useEffect need to be defined and then called
    const addListener = async () => {
      try {
        loadCollection(config, dispatch);
      } catch (e) {
        console.error(e);
      }
    }

    addListener();
    
  }, [config, dispatch]);

  /* ... */
}

对不起,我在代码上犯了一个错误,请你在同一期之后重新阅读一遍好吗。您仍然没有返回任何内容。似乎他正在尝试一个侦听器,该侦听器侦听数据库中的更改,然后在有人进行更改时添加任何项目