如何在像forEach reduce这样的javascript函数中使用promise函数?
我使用的承诺函数如下:如何在像forEach reduce这样的javascript函数中使用promise函数?,javascript,typescript,functional-programming,promise,async-await,Javascript,Typescript,Functional Programming,Promise,Async Await,我使用的承诺函数如下: // WORK let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc}; for (let i = 0; i < rv.copyDetailList.length; i ++) { const item = rv.copyDetailList[i]; const v = await convertCommonInfo(item)
// WORK
let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc};
for (let i = 0; i < rv.copyDetailList.length; i ++) {
const item = rv.copyDetailList[i];
const v = await convertCommonInfo(item);
if (!item.errorId) {
res.approveList.push(v);
} else {
res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
}
error TS2345: Argument of type '(prev: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, item: Resp...' is not assignable to parameter of type '(previousValue: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, c...'.
Type 'Promise<void>' is not assignable to type '{ approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }'.
Property 'approveList' is missing in type 'Promise<void>'.
我发现forEach
功能无法工作:
// NOT WORK, not wait async function
rv.copyDetailList.forEach(async function(item) {
const v = await convertCommonInfo(item);
if (!item.errorId) {
res.approveList.push(v);
} else {
res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
});
这不起作用,它只返回init值事实上,这让我很困惑,因为我正在等待函数,为什么不工作?
即使我想使用reduce
功能:
// NOT WORK, Typescirpt can not compile
rv.copyDetailList.reduce(async function(prev, item) {
const v = await convertCommonInfo(item);
if (!item.errorId) {
prev.approveList.push(v);
} else {
prev.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
}, res);
但由于我使用的是Typescript
,所以我得到了如下错误:
// WORK
let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc};
for (let i = 0; i < rv.copyDetailList.length; i ++) {
const item = rv.copyDetailList[i];
const v = await convertCommonInfo(item);
if (!item.errorId) {
res.approveList.push(v);
} else {
res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
}
error TS2345: Argument of type '(prev: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, item: Resp...' is not assignable to parameter of type '(previousValue: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, c...'.
Type 'Promise<void>' is not assignable to type '{ approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }'.
Property 'approveList' is missing in type 'Promise<void>'.
error TS2345:type'(prev:{approveList:any[];rejectList:any[];errorId:string;errorDesc:string;},item:Resp…)的参数不能分配给类型的参数(previousValue:{approveList:any[];rejectList:any[];errorId:string;errorDesc:string;},c.。)。
类型“Promise”不能分配给类型“{approveList:any[];rejectList:any[];errorId:string;errorDesc:string;}”。
类型“Promise”中缺少属性“approveList”。
所以我想知道两件事:
forEach
wait无法工作?您可能正在反向处理此问题。通常,您希望使用
compose
组合所有转换,并将该组合函数传递给。然后
承诺的处理程序:
// assumes curried times and add functions
let tranformData = _.compose(square, times(2), add(3));
let foo = fetchNumberAsync() // returns a promise of 3
.then(transformData)
.catch(err => doSomethingWithError(err));
foo.then(n => console.log(n)); // prints 144 to the console ((3 + 3) * 2) ** 2
与备选方案相比:
// clear but wasteful
let foo = fetchNumberAsync()
.then(n => n + 3)
.then(n => n * 2)
.then(n => n ** 2)
或
使用
compose
(尤其是使用memoize
)是一条很好的中间道路。为什么forEach Wait不能工作?
您为forEach提供了一个异步函数,但在forEach函数的实现中,它不是等待的。我猜forEach是这样的:
Array.prototype.forEach = function (func) {
for (let item of this) {
func(item); // Note here, there is no "await" in front of it
}
}
我可以在reduce中使用promise函数吗?
不,您不能使用与上述相同的原因
通过“co”平滑代码的替代方法如下所示:
let ret = await rv.copyDetailList.map(co(function * (item) {
const v = yield convertCommonInfo(item);
if (!item.errorId) {
res.approveList.push(v);
} else {
res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
}));
如果您的最终目标是在每次迭代同时运行的情况下实现单个遍历,那么可以使用各种库来提供一个“异步遍历”,与您所要查找的内容类似 一个这样的库是,它提供了一个并行.each迭代器,可以很好地与async/await配合使用 使用此库,您的代码可能如下所示
let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc};
await Parallel.each(rv.copyDetailList, async (item) => {
var v = await convertCommonInfo(item);
if (!item.errorId)
res.approveList.push(v);
else
res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
});
可能的重复(对于reduce
,相同)