[英]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
/ async
和Promise.then()
语法。 混合这两种语法不是错误,但我不建议这样做。 坚持await
/ async
您的操作实际上现在没有返回任何值,因为您的内部then
function 没有返回任何值。 唯一的return
是在then
内部是在x.map
回调中。 await syncItems
是映射器的返回值,而不是您的 function 的返回值。
现在,这是您的 thunk 所做的:
void
的Promise
我相信你想要的是这样的:
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.