在使用Restivus定义的端点内,我调用AWS返回一个对象。我使用setTimeout函数模拟了这个函数。
async的目的当然不是为了阻塞服务器。但是,我必须等待forEach
函数完成,以便将newData
数组返回给客户端。
目前,终点会立即返回。如何将整个forEach
函数作为一个同步函数运行。换句话说,直到forEach函数完成,端点才会返回?
服务器>下载.js
class downloadClassed {
constructor(){};
downoadFile(key, ETag) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({key, ETag, status: "done"});
}, 1000 + Math.random() * 3000);
});
}
}
downloadClass = downloadClassed;
server>routes.js
// inside endpoint
const cloudArray = [{ETag: 1, key: "a"}, {ETag: 2, key: "b"}, {ETag: 3, key: "c"}]
let newData = [];
cloudArray.forEach(function(cloudItem, index) {
const downloadclass = new downloadClass();
downloadclass.downoadFile(cloudItem.key, cloudItem.ETag)
.then((data) => {
console.log(data);
newData.push(data);
})
})
console.log('return newData Array to client');
return JSON.stringify(data: newData);
你想要的并不完全可能,但有办法解决。
这是不可能的,因为函数调用总是同步的,不能让它"等待"异步进程完成后再返回。这就是为什么我们使用回调,或围绕它们的其他抽象,如promise和事件处理程序。
当你想在异步进程结束后做某事时,你可以注册一个回调。或者使用promise,这是一种使用回调作为底层实现的机制,但提供了一些优势。因此,您需要创建一个接收回调或返回promise的函数。
在您的情况下,您希望等待几个异步进程完成(下载)。Promise.all
在这方面非常有用。你可以这样实现:
// You didn't include a signature, I made up a name for the function.
function downloadData() {
const cloudArray = [{ETag: 1, key: "a"}, {ETag: 2, key: "b"}, {ETag: 3, key: "c"}]
// cloudArray.map(fn) creates an array with the results of calling
// fn on the values of cloudArray.
const dataPromises = cloudArray.map(function (cloudItem, index) {
const downloadclass = new downloadClass()
// This returns a Promise so dataPromises will be an array of them.
return downloadclass.downoadFile(cloudItem.key, cloudItem.ETag)
})
// Using Promise.all(dataPromises), we return a promise that's
// fulfilled after all the download promises are...
return Promise.all(dataPromises)
.then((dataArray) => {
// ...and resolves to a JSON string for this object
return JSON.stringify({data: dataArray})
})
}
函数的调用者将收到一个Promise,它要求他们使用.then(someFunction)
来使用数据,如下所示:
downloadData()
.then((data) => {
console.log("look what I got from the internet!", data)
})
你可以在这里阅读一篇关于承诺的温和介绍。有一些很棒的库可以处理promise和做惯用的东西(代码越少越有价值)。蓝鸟、q和rsvp就是其中之一。