简体   繁体   English

按顺序执行承诺映射

[英]Execute promises map sequentially

I have written a function that is being called in a loop (map) and that function is using promises.我编写了一个在循环(映射)中调用的函数,并且该函数使用了 Promise。 Now, I want that function to run synchronously and exit before its next instance is called.现在,我希望该函数同步运行并在调用其下一个实例之前退出。

 function t1(){ let arr1 = [1,2,3,4,5]; return Promise.map(arr1, (val) =>{ const params = { "param1" : val1 }; return t2(params); }); } function t2(event){ return Promise.resolve() .then({ //do something //code doesn't reach here in sync manner. all five instance are invoked and then code reaches here for first instance and so on }) .then({ //promise chaining. do something more }) }

t2 is beingcalled five times, but I want each instance to be called only after the instance before it has returned the value. t2 被调用五次,但我希望每个实例只在实例返回值之前调用。 Currently its not behaving like that but invoking the function five times in parallel.目前它的行为不是那样,而是并行调用该函数五次。

I can't use async/await due to project limitations.由于项目限制,我无法使用 async/await。

The problem with your current code is that Promise.prototype.map , like forEach , does not wait for asynchronous functions called inside it to complete.您当前代码的问题在于Promise.prototype.mapforEach一样,不会等待在其中调用的异步函数完成。 (No asynchronous call will ever be waited for unless you tell the interpreter to do so explicitly with await or .then ) (除非您使用await.then明确告诉解释器这样做,否则不会等待任何异步调用)

Have t1 await each call of t2 :t1等待t2每次调用:

async function t1(){
  let arr1 = [1,2,3,4,5];
  const results = [];
  for (const val of arr1) {
    results.push(await t2(val));
  }
  return results;
}

Or if you want to use reduce instead of async / await :或者,如果您想使用reduce而不是async / await

 const delay = () => new Promise(res => setTimeout(res, 500)); function t1(){ let arr1 = [1,2,3,4,5]; return arr1.reduce((lastProm, val) => lastProm.then( (resultArrSoFar) => t2(val) .then(result => [...resultArrSoFar, result]) ), Promise.resolve([])); } function t2(event){ return delay().then(() => { console.log('iter'); return event; }); } t1() .then(results => console.log('end t1', results));

Or, if you need the sequential functionality to be encapsulated in t2, then have t2 have a semi-persistent variable of the previous Promise it generated:或者,如果您需要将顺序功能封装在 t2 中,那么让 t2 具有它生成的前一个 Promise 的半持久变量:

 const delay = () => new Promise(res => setTimeout(res, 500)); const t1 = () => { return Promise.all([1, 2, 3, 4].map(t2)); }; const t2 = (() => { let lastProm = Promise.resolve(); return (event) => { const nextProm = lastProm .catch(() => null) // you may or may not want to catch here .then(() => { // do something with event console.log('processing event'); return delay().then(() => event); }); lastProm = nextProm; return nextProm; }; })(); t1().then(results => console.log('t1 done', results));

(function loop(index) {
    const next = promiseArray[index];
    if (!next) {
        return;
    }
    next.then((response) => {
        // do Something before next
        loop(index + 1);
    }).catch(e => {
        console.error(e);
        loop(index + 1);
    });
})(0 /* startIndex */)

Here is what running Promises sequentially would look like when using .reduce() in combination with async/await:以下是将.reduce()与 async/await 结合使用时按顺序运行 Promise 的样子:

 async function main() { const t2 = (v) => Promise.resolve(v*2) const arr1 = [1,2,3,4,5]; const arr1_mapped = await arr1.reduce(async (allAsync, val) => { const all = await allAsync all.push(await t2(val) /* <-- your async transformation */) return all }, []) console.log(arr1_mapped) } main()

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM