繁体   English   中英

异步确实等待在 redux-thunk function 中返回数据

[英]Async does wait for data to be returned in a redux-thunk function

我正在尝试使用来自我的 mongo-db realm 数据库的数据填充我的 redux 存储。 每当我在下面运行 function 时,它都会正常执行,但问题是数据会延迟,最终无法到达我的 redux 商店。

我的重击 function:

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)
         }
      });
  }

预期结果:一旦addItemsTest返回某些内容,我的 redux 商店应该有这些数据:

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

实际结果: 控制台结果

混合语法

您正在以一种非常令人困惑的方式组合await / asyncPromise.then()语法。 混合这两种语法不是错误,但我不建议这样做。 坚持await / async

无效回归

您的操作实际上现在没有返回任何值,因为您的内部then function 没有返回任何值。 唯一的return是在then内部是在x.map回调中。 await syncItems映射器的返回值,而不是您的 function 的返回值。

现在,这是您的 thunk 所做的:

  • 打开连接
  • 从 realm 获取项目
  • 为记录更改的那些项目添加一个侦听器
  • 返回解析为voidPromise

解决方案

我相信你想要的是这样的:

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");
  }
);

您不需要catch错误,因为createAsyncThunk将通过调度错误操作来处理错误。

编辑:聆听变化

您的意图似乎是将您的 redux 存储与您的 Realm 集合中的更改同步。 因此,您希望向集合中添加一个侦听器,该侦听器通过一些操作调用dispatch来处理更改。

在这里,我假设此操作需要一个包含集合中所有项目的数组。 像这样的东西:

const processItems = createAction("processItems", (items: Item[]) => ({
  payload: items
}));

更换 state 中的整个阵列是最简单的方法。 当您将项目对象替换为相同版本时,它会导致一些不必要的重新渲染,但这没什么大不了的。

或者,您可以传递更改的特定属性,例如insertions ,并根据具体情况在减速器中处理它们。

为了添加调度processItems的侦听器,我们需要访问两个变量:realm config和 redux dispatch 您可以在您的组件中执行此操作,也可以通过调用“init”操作来执行此操作。 我不认为有太大的区别。 如果你愿意,你可以在你的 reducer 中做一些事情来响应“init”动作。

这是一个 function 添加监听器。 Realm.Results object 是“类数组”但不完全是数组,因此我们使用[...x]将其转换为数组。

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

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]));
  });
}

通过中间的addListener动作创建者添加监听器:

export const addListener = createAsyncThunk(
  "init",
  async (config: Realm.Configuration, { dispatch }) => {
    return await loadCollection(config, dispatch);
  }
);

// is config a prop or an imported global variable?
const InitComponent = ({config}: {config: Realm.Configuration}) => {
  const dispatch = useDispatch();

  useEffect( () => {
    dispatch(addListener(config));
  }, [config, dispatch]);

  /* ... */
}

直接添加监听器:

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]);

  /* ... */
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM