流星:返回承诺's,然后再响应HTTP发布请求

Meteor: return Promise's before responding to the HTTP post request

本文关键字:HTTP 响应 布请求 请求 然后 承诺 返回 流星      更新时间:2023-09-26

在使用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就是其中之一。