等待异步调用完成并返回

时间:2019-08-29 03:15:06

标签: javascript node.js asynchronous

我需要在nodejs中编写一些Cloud Functions。这个特定的Cloud Function需要遍历URL数组并对第三方API进行一些异步调用。

这里有一些占位符代码,模仿了我想做的事情,改编自here

function checkPhotos(photos) {
  var checkedPhotos = [];
  var promiseArray = photos.map(asyncFunction);

  Promise.all(promiseArray).then(results => {
    console.log('results are: ', results)
    results.forEach(result => { checkedPhotos.push(result) });
  })

  // I want to block here until the Promise.all call above completes
  // but it does not block, it returns [] immediately while the async
  // calls run
  return checkedPhotos;
}

// This is a pretend async function to simulate the third party API
function asyncFunction(photo) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("in async function, photo is " + photo)
      resolve(photo)
    }, Math.random()*2000)
  })
}

然后我调用函数:

var photos = ['https://example.com/example.jpg', 'https://example.com/example2.jpg'];
var checkedPhotos = checkPhotos(photos);

我希望checkedPhotos包含results中的值,但是起初它是一个空数组,然后异步调用完成,并填充了该数组。如何使checkPhotos()阻塞直到所有异步调用都完成,以便我可以将checkedPhotos作为完整填充的数组返回?

3 个答案:

答案 0 :(得分:1)

在您的示例中,您必须在Promise.all回调函数中返回值,因为Promise.all将订阅该异步调用,并要求db引擎在完成后立即运行该回调函数。另外,您需要订阅Promise.all.the(cb).catch(cb)中的catch函数,并传递回叫函数Incas出错,也会返回一些信息。

等待所有诺言完成的另一种方法是,您必须使用async和await关键字,只需在async之前添加function checkPhotos(...关键字,并在{{1}之前添加广告await关键字}},这将告诉js引擎,当您收到响应时,您需要在await行下面运行代码。

如果您要从另一个函数中调用此函数,则需要其他函数来等待此问题被解决,您可以简单地使用上层异步等待解决方案,并按此方法在调用订阅时回叫。

Promise.all...

这就是js处理异步调用的方式,它不会阻止您的代码(事件循环),它只允许您订阅异步调用并传递一个回调函数,以在JavaScript得到响应后执行。

答案 1 :(得分:1)

我建议只返回Promise.all,因为您没有在函数内做任何事情。如果要执行任何操作,请使用async / await等待结果。

async function checkPhotos(photos) {
    var checkedPhotos = [];
    var promiseArray = photos.map(asyncFunction);

    const results = await Promise.all(promiseArray);
    console.log('results are: ', results)
    results.forEach(result => { checkedPhotos.push(result) });
    // Some other action
    return checkedPhotos;
}

不采取行动

function checkPhotos(photos) {
  var promiseArray = photos.map(asyncFunction);
  return Promise.all(promiseArray);
}

async function somefunc(){
    await checkPhotos(photos);
} 

答案 2 :(得分:-1)

为什么不使用异步等待?

async function checkPhotos(photos) {
  var checkedPhotos = [];

  for (const photo of photos) {
    let result = await asyncFunction(photo);
    checkedPhotos.push(result);
  }

  return checkedPhotos;
}

然后这样称呼它:

var photos = ['https://example.com/example.jpg', 'https://example.com/example2.jpg'];
checkPhotos(photos)
.then(checkedPhotos => {
  // do something
})