简体   繁体   English

如何在javascript函数函数中使用promise函数,如forEach reduce?

[英]how to use promise function in javascript functional function like forEach reduce?

I am using promise function like this: 我正在使用这样的promise函数:

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

This works well, but I want to try to use some functional function, I find that I have to use map then reduce 这很好用,但我想尝试使用一些功能函数,我发现我必须使用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});

I find that forEach function can not work: 我发现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}));
    }
});

This doesn't work, it just return init value. 这不起作用,只返回init值。 In fact this puzzle me, sine I await the function, why not work? 事实上这让我感到困惑,我正await这个功能,为什么不工作呢?

Even I want to use reduce function: 即使我想使用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);

But since I am using Typescript , I got error like this: 但是因为我使用的是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>'.

So I want to know two things: 所以我想知道两件事:

  1. Why forEach await can not work? 为什么forEach等待都行不通?
  2. Can I use promise function in reduce? 我可以在减少中使用promise函数吗?

You are possibly approaching this backwards. 你可能正在倒退这个。 Generally, you want to use compose to combine all the transformations and pass that composed function to the .then handler of a promise: 通常,您希望使用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

Compare to the alternatives: 与替代品相比:

// clear but wasteful
let foo = fetchNumberAsync()
  .then(n => n + 3)
  .then(n => n * 2)
  .then(n => n ** 2)

or 要么

// performant but opaque
let foo = fetchNumberAsync().then(n => ((n + 3) * 2) ** 2)

Using compose (especially with memoize ) is a good middle road. 使用compose (特别是memoize )是一条很好的中间道路。

Why forEach await can not work? 为什么每个等待都行不通? You provide an async function to forEach, but inside the implementation of forEach function, it is not awaited. 您为forEach提供了一个异步函数,但在forEach函数的实现中,它是不等的。 I guess the forEach is like that: 我想forEach是这样的:

Array.prototype.forEach = function (func) {
    for (let item of this) {
        func(item);    // Note here, there is no "await" in front of it 
    }
}

Can I use promise function in reduce? 我可以在减少中使用promise函数吗? No, you cannot same reason as above. 不,你不能像上面那样理由。

The alternative way via "co" to smooth your code is like the below: 通过“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}));
    }
}));

If your ultimate goal is to achieve a single traversal where each iteration runs concurrently, then there are various libraries available that provide an "asynchronous each" along the lines of what it sounds like you're looking for. 如果你的最终目标是实现每次迭代同时运行的单个遍历,那么有各种各样的库可以提供一个“异步” ,就像你正在寻找的那样。

One such library is async-parallel , which offers a Parallel.each iterator that works nicely with async/await. 一个这样的库是异步并行的 ,它提供了一个与async / await很好地工作的Parallel.each迭代器。

Using this library your code could look like this... 使用这个库你的代码看起来像这样......

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

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

相关问题 如何使用 reduce function JavaScript - how to use the reduce function JavaScript 在javascript函数式编程中,如何使用reduce函数查找一组数组之间的交集/并集? - How do you use a reduce function to find the intersection/union between a set of arrays in javascript functional programming? 如何在javascript中使用reduce函数调用promise中的函数 - How to call a function inside a promise with reduce function in javascript 有没有像数组中的foreach这样的函数的函数形式,可以产生Javascript中的所有对 - Is there a functional form of a function like foreach over an array that yields all pairs in Javascript JavaScript forEach function:未捕获(承诺)类型错误 - JavaScript forEach function: Uncaught (in promise) TypeError 调用带有promise的函数到foreach中 - Calling a function with a promise into a foreach 使用compose函数和Array.reduce进行JavaScript函数编程 - JavaScript functional programing with compose function and Array.reduce 需要一些有关如何在JavaScript中使用函数式编程来重用函数的想法 - Need some ideas on how to use functional programming in JavaScript to reuse a function 在 reduce 函数中使用函数参数:Javascript - Use function argument inside reduce function : Javascript 将forEach函数变成化简函数 - Turn a forEach function into a reduce function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM