首页 > 解决方案 > Nodejs 中的等待、链式承诺和流控制

问题描述

我想一个接一个地执行函数,使用上一个调用返回的值进入下一个。

我使用以下代码使其工作:

var i = 0;

async function testn() {
  console.log('%s -> test%s (i = %s)', new Date(), i+1, i++);
  setTimeout(console.log, timeout1, ' value of i in test%s : ', i, i);
  console.log('%s <- test%s (i = %s)', new Date(), i, i);
  return {result: 0};
}

async function wrapIt() {
  await testn()
    .then(await testn())
    .then(await testn())
    .catch((error) => {
      console.log('caught %s', error);
    })
    .finally(() => {
      console.log('finally %s', i);
    })
}

wrapIt();

这是输出:

2021-07-14T12:23:56.677Z -> test1 (i = 0)
2021-07-14T12:23:56.678Z <- test1 (i = 1)
2021-07-14T12:23:56.678Z -> test2 (i = 1)
2021-07-14T12:23:56.678Z <- test2 (i = 2)
2021-07-14T12:23:56.678Z -> test3 (i = 2)
2021-07-14T12:23:56.678Z <- test3 (i = 3)
finally 3
 value of i in test1 :  1
 value of i in test2 :  2
 value of i in test3 :  3

如果我使用显式 Promises 而不是隐式返回 Promise 的async关键字,则行为会发生变化(查看两次调用 testn() 之间的延迟)。

var i = 0;
var timeout1 = 5000;
var timeout2 = 1000;

async function testn() {
  return new Promise(function (resolve,reject) {
    console.log('%s -> test%s (i = %s)', new Date(), i+1, i++);
    setTimeout(console.log, timeout1, ' value of i in test%s : ', i, i);
    console.log('%s <- test%s (i = %s)', new Date(), i, i);
    setTimeout(() => {resolve({result: 0})}, timeout2);
  })
}

async function wrapIt() {
  await testn()
    .then(await testn())
    .then(await testn())
    .catch((error) => {
      console.log('caught %s', error);
    })
    .finally(() => {
      console.log('finally %s', i);
    })
}

这是输出:

2021-07-14T12:20:27.670Z -> test1 (i = 0)
2021-07-14T12:20:27.671Z <- test1 (i = 1)
2021-07-14T12:20:27.671Z -> test2 (i = 1)
2021-07-14T12:20:27.671Z <- test2 (i = 2)
2021-07-14T12:20:28.672Z -> test3 (i = 2)
2021-07-14T12:20:28.672Z <- test3 (i = 3)
finally 3
 value of i in test1 :  1
 value of i in test2 :  2
 value of i in test3 :  3

为什么延迟1 s。仅在第 2 次和第 3 次调用之间有效,而不在第 1 次和第 2 次调用之间有效?

标签: node.jsasync-await

解决方案


如果您的问题与 无关setTimeout,您可以通过await以下方式使用类似同步函数调用的值:

async function testn(arg) {
      console.log(arg++);
      return arg;
}
 
async function wrapIt() {
   const res1 = await testn(0);
   const res2 = await testn(res1);
   const res3 = await testn(res2);
   console.log('finally %s', res3);     
}

wrapIt();


推荐阅读