javascript - 使用 Google Cloud Functions Node.JS 等待多个异步函数的正确方法

标签 javascript node.js asynchronous async-await google-cloud-functions

我对 Javascript 的异步世界还比较陌生。我的函数对 Firebase Admin SDK 进行了一些调用,并对第三方 API 进行了一些提取请求。该功能有效,但每隔一段时间我就会收到 socket hang up 错误。我基本上想等到所有 await 函数完成后再发送 res.end(),但看起来我在使用 async/await 方面做错了什么>.

我的函数完成(看起来它命中了 res.end())但它一直在继续:

enter image description here

然后奇怪的是,来自相同执行 ID 的错误出现在以下执行 ID 中:

enter image description here

以下是我构建代码的方式:

exports.myFunction = async (req, res) => {

    // parse the body...

    // if it's a closed order 
    if (json.hasOwnProperty('closed_at')) {

        // get order object from orders directory
        await ordersRef.once("value", async function(snapshot) {
            var orderResponseObj = snapshot.val();

            // do some stuff with orderResponseObj

            // ** res.end() CALLED BEFORE THIS HAPPENS **
            await deleteRef.once("value", async function(snapshot) {
                var deleteResponseObj = snapshot.val();
                // do some stuff with the delete object
            });

            // get object from shop directory
            await shopInfoRef.once("value", async function(snapshot) {
                var firebaseResponseObj = snapshot.val();

                await updateInventory.updateInventory(); // do some fetch request to 3rd party API

                await deleteProduct.deleteProduct(); // do another fetch call to 3rd party API
            });
        });
    }
    // terminate the cloud function
    res.end();
}

最佳答案

所以你有一些嵌套的 promise ,实际上不会等待所有 promise 完成,你的结构是这样的:

|   1 exports.myFunction
|   |   1 ordersRef.once
|   |   |   1 deleteRef.once
|   |   |   2 shopInfoRef.once
|   |   |   |   1 updateInventory.updateInventory
|   |   |   |   2 deleteProduct.deleteProduct

事实上,您的异步函数只会等待第一个较低级别的 promise ,因此例如 deleteRef.once 只会等待 shopInfoRef.once,但不会对于 updateInventory.updateInventory。这意味着您的顶级 exports.myFunction 将只等待 ordersRef.once 解析,忽略其余部分。数字表示 promise 的执行顺序,因为您对所有这些都使用 await,所以我们没有在同一级别触发的 promise 一起触发(没有重复的数字)。

现在为了等待所有函数循环的结束,您可以实现自己的 promise 链。查看您的代码,等待的最后一个 promise 是 deleteProduct.deleteProduct,因为当您到达该点时,由于所有 await 关键字,任何其他 promise 都已解决.

exports.myFunction = async (req, res) => {

    // parse the body...

    // if it's a closed order 
    if (json.hasOwnProperty('closed_at')) {
     let awaiter = new Promise((resolve) => {
        // get order object from orders directory
        await ordersRef.once("value", async function(snapshot) {
            var orderResponseObj = snapshot.val();

            // do some stuff with orderResponseObj

            // ** res.end() CALLED BEFORE THIS HAPPENS **
            await deleteRef.once("value", async function(snapshot) {
                var deleteResponseObj = snapshot.val();
                // do some stuff with the delete object
            });

            // get object from shop directory
            await shopInfoRef.once("value", async function(snapshot) {
                var firebaseResponseObj = snapshot.val();

                await updateInventory.updateInventory(); // do some fetch request to 3rd party API

                await deleteProduct.deleteProduct(); // do another fetch call to 3rd party API

                resolve(); // we put resolve in the very last point of the chain
            });
        });
      });

      // await make the execution of your async function
      // wait until the "resolve" function of our "awaiter"
      // promise is called, so at the very last of the chain
      await awaiter;
    }
    // terminate the cloud function
    res.end();
}

显然,您可以将代码压缩为类似 await new Promise(resolve => { ... }) 的形式,但为了清楚起见,我将这两个句子分开。

新结构结果如下:

|   1 exports.myFunction
|   |   1 awaiter
|   |   -   1 ordersRef.once
|   |   -   |   1 deleteRef.once
|   |   -   |   2 shopInfoRef.once
|   |   -   |   |   1 updateInventory.updateInventory
|   |   -   |   |   2 deleteProduct.deleteProduct
|   |   ----------> 3 awaiter.resolve

关于javascript - 使用 Google Cloud Functions Node.JS 等待多个异步函数的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66180561/

相关文章:

html - Node.js Web 应用程序中的 ECONNRESET、MongoNetworkError

node.js - 如何访问部署在aws elasticbeanstalk中的文件

基于WCF任务的异步回调

javascript - 根据多个选项卡中的cookie更新div元素值

javascript - 1925 年之前的 JavaScript 日期中的错误分钟和秒

javascript - 从 GWT 调用框架 js

javascript - getElementsByTagName 不起作用

javascript - 使用 PhantomJS/CasperJS 上传 JS 文件

javascript - Node js 返回不返回任何内容

javascript - 返回具有异步功能的事件主机