我正在使用这样的承诺函数:
// 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}));
}
}
这很好用,但我想尝试使用一些功能函数,我发现我必须使用map
然后减少
// WORK, But with two traversal
const dataList = await promise.all(rv.copyDetailList.map((item) => convertCommonInfo(item)));
const res = dataList.reduce((obj, v, i) => {
const item = rv.copyDetailList[i];
if (!item.errorId) {
obj.approveList.push(v);
} else {
obj.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg}));
}
return obj;
}, {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc});
我发现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}));
}
});
这不起作用,它只返回初始值。 事实上,这让我感到困惑,正义我await
这个功能,为什么不起作用?
即使我想使用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
,我收到的错误是这样的:
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
等待不起作用? 答案 0 :(得分:1)
你可能会倒退。通常,您希望使用compose
来组合所有转换并将该组合函数传递给promise的.then
处理程序:
// 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)
或
// performant but opaque
let foo = fetchNumberAsync().then(n => ((n + 3) * 2) ** 2)
使用compose
(特别是memoize
)是一条很好的中途道路。
答案 1 :(得分:1)
为什么每个等待都无法正常工作? 您为forEach提供了一个异步函数,但在forEach函数的实现中,它是不等的。我想forEach是这样的:
<img src="prof.jpg" id="pictureToShow" />
我可以在reduce中使用promise函数吗? 不,你不能像上面那样理由。
通过“co”来替代代码的替代方法如下所示:
Array.prototype.forEach = function (func) {
for (let item of this) {
func(item); // Note here, there is no "await" in front of it
}
}
答案 2 :(得分:1)
如果您的最终目标是实现每次迭代同时运行的单个遍历,那么可以使用各种库来提供&#34;异步的每个&#34; 沿着它的行听起来像你正在寻找。
一个这样的库是async-parallel,它提供了一个 Parallel.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}));
});