javascript - 异步确实等待数据在 redux-thunk 函数中返回
问题描述
我正在尝试使用来自我的 mongo-db 领域数据库的数据填充我的 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()
语法。混合这两种语法不是错误,但我不建议这样做。坚持只是await
/async
无效回归
您的操作实际上现在没有返回任何值,因为您的内部then
函数没有返回任何内容。唯一return
的 is 内部then
是在x.map
回调中。 是mapperawait syncItems
的返回值,而不是您的函数。
现在,这是您的 thunk 所做的:
- 打开连接
- 从领域获取物品
- 为记录更改的那些项目添加一个侦听器
- 返回一个
Promise
解析为void
解决方案
我相信你想要的是这样的:
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
}));
更换您所在州的整个阵列是最简单的方法。当您将项目对象替换为相同版本时,它会导致一些不必要的重新渲染,但这没什么大不了的。
或者,您可以传递更改的特定属性,例如insertions
并根据具体情况在减速器中处理它们。
为了添加一个 dispatch 的监听器processItems
,我们需要访问两个变量:realmconfig
和 redux dispatch
。您可以在您的组件中执行此操作,也可以通过调用“init”操作来执行此操作。我不认为有太大的区别。如果你愿意,你可以在你的 reducer 中做一些事情来响应“init”动作。
这是一个添加监听器的函数。该Realm.Results
对象是“类数组”,但不完全是数组,因此我们[...x]
将其转换为数组。
仅供参考,此功能可能会引发错误。如果使用 in ,这很好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]);
/* ... */
}
推荐阅读
- google-cloud-firestore - SwiftUI 和 Picker 和 FireStore 返回文档 ID 不落
- flask - url_for 的烧瓶蓝图问题
- wordpress - 触发高级自定义字段 (ACF) 'acf/save_post' 操作
- python - PayPal 是否仍支持通过 HTTP REST API 的活动报告和余额?
- flutter - 项目目录中没有 Podfile | 颤振 - firebase 身份验证
- minecraft - WorldEdit 如何处理画笔?
- python - 以 JSON 格式获取存储过程结果
- java - 我需要重命名我在java中生成的json对象的键
- html - 从参考表中提取样式格式
- php - 如何在 PHP 一个班轮中在几分钟内转换字符串“4H6M”?