我需要在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
作为完整填充的数组返回?
答案 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
})