foreach具有多种功能的异步

时间:2019-01-02 08:32:56

标签: javascript asynchronous promise async-await

我有一个问题,我无法在异步foreach许诺中下订单。希望你能帮助我。

我有3个(承诺)函数,我希望在再次运行它们之前在foreach中运行它们。

以下代码:

var env = [
  'dev',
  'prd',
  'tst',
]

env.forEach(currentEnv => {
  Promise.resolve()
  .then(firstFunction(currentEnv))
  .then(secondFunction(currentEnv))
});

function firstFunction(env) {
  new Promise(resolve => {
    setTimeout(() => {
      console.log('firstFunction ' + env)
      resolve();
    }, 2000);

  }).catch((error) => {
    console.log('something went wrong' + env + "error: " + error);
  });

};

function secondFunction(env) {
  new Promise(resolve => {
    setTimeout(() => {
      console.log('secondFunction ' + env)
      resolve();

    }, 1000);
  }).catch(() => {
    console.log('something went wrong')
  });
}

结果:

secondFunction dev
secondFunction prd
secondFunction tst
firstFunction dev
firstFunction prd
firstFunction tst

预期:

firstFunction dev
secondFunction dev
firstFunction prd
secondFunction prd
firstFunction tst
secondFunction tst

希望你们能帮助我。

2 个答案:

答案 0 :(得分:1)

首先,您需要实际从函数中返回promise,并将函数(不是函数调用的结果)提供给.then()回调。

var env = [
  'dev',
  'prd',
  'tst',
]

env.forEach(currentEnv => {
  Promise.resolve()
  .then(() => firstFunction(currentEnv))
  .then(() => secondFunction(currentEnv))
});

function firstFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('firstFunction ' + env)
      resolve();
    }, 2000);

  }).catch((error) => {
    console.log('something went wrong' + env + "error: " + error);
  });

};

function secondFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('secondFunction ' + env)
      resolve();

    }, 1000);
  }).catch(() => {
    console.log('something went wrong')
  });
}

这样做足以使您的呼叫按“所有firstFunction()个呼叫然后所有secondFunction()个呼叫”的顺序排列。

但是,如果您需要创建下一个环境来等待当前环境的完成,则可以使用异步迭代器构造。这是一个相对较新的功能,因此我假设您至少使用Node 10.x。

var env = [
  'dev',
  'prd',
  'tst',
];


function firstFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('firstFunction ' + env)
      resolve();
    }, 2000);

  }).catch((error) => {
    console.log('something went wrong' + env + "error: " + error);
  });

};

function secondFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('secondFunction ' + env)
      resolve();
    }, 1000);
  }).catch(() => {
    console.log('something went wrong')
  });
}

async function *getAsyncIterator(env) {
	for (const currentEnv of env) {
  	await firstFunction(currentEnv);
    await secondFunction(currentEnv);
    yield currentEnv;
	}
}

async function doStuff() {
  for await (const currentEnv of getAsyncIterator(env)) {
    console.log(`Complete work on ${currentEnv}`)
  }
}

doStuff();

更新:

最后,如果必须支持某些较旧的节点版本,第三个选择是应用递归算法。

var env = [
  'dev',
  'prd',
  'tst',
];

function firstFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('firstFunction ' + env)
      resolve();
    }, 2000);

  }).catch((error) => {
    console.log('something went wrong' + env + "error: " + error);
  });

};

function secondFunction(env) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('secondFunction ' + env)
      resolve();
    }, 1000);
  }).catch(() => {
    console.log('something went wrong')
  });
}

function doStuff(env = []) {
	if (env.length === 0) return;
  
	const [ currentEnv, ...restEnvs ] = env;
  
	return Promise.resolve()
  	.then(() => firstFunction(currentEnv))
    .then(() => secondFunction(currentEnv))
    .then(() => doStuff(restEnvs));
}

doStuff(env).then(() => console.log('job done'));

答案 1 :(得分:0)

您好,非常感谢您的帮助。我玩了一段时间,想出了这个解决方案:

let promise = Promise.resolve();
env.forEach(thisEnv => {
  promise = promise
    .then(() => firstFunction(thisEnv))
    .then(() => secondFunction(thisEnv))
});

promise.then(() => {
  doneBuilding()
});