顺序执行承诺图

时间:2019-08-30 07:10:32

标签: javascript node.js promise

我编写了一个在循环(映射)中调用的函数,并且该函数正在使用promises。现在,我希望该函数同步运行并在调用下一个实例之前退出。

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被调用了五次,但是我希望每个实例仅在实例返回值之前被调用。 目前,它的行为并非如此,而是并行调用了五次。

由于项目限制,我无法使用async / await。

3 个答案:

答案 0 :(得分:4)

当前代码的问题在于,Promise.prototype.mapforEach一样,不等待内部调用的异步函数完成。 (除非您告诉解释器使用await.then显式地执行此操作,否则不会等待异步调用。)

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

或者如果您想使用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));

或者,如果您需要将顺序功能封装在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));

答案 1 :(得分:1)

(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 */)

答案 2 :(得分:-2)

这是将.reduce()与async / await结合使用时按顺序运行Promises的样子:

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
  }, Promise.resolve([]))

  console.log(arr1_mapped)

}

main()