在Firebase Cloud Functions中使用异步/等待时返回承诺

时间:2018-08-20 23:10:31

标签: javascript firebase async-await google-cloud-functions

因此,我很高兴一直在使用async / await,因为Firebase Cloud Functions支持节点8。我正在努力做一件事情。使用可调用函数时,系统会告知您必须在函数中返回一个promise,否则它将无法正常工作。使用原始的诺言时,我很清楚如何使用它:

Eigen::Map<Eigen::SparseMatrix<float>> sparse_map(num_rows, num_cols, num_non_zeros,
                             original_outer_index_ptr, original_inner_index_ptr,
                             original_values_ptr);

但是现在,异步等待着,我不确定如何返回这个“承诺链”:

exports.createBankAccount = functions.region('europe-west1').https.onCall((data, context) => {
    return promiseMethod().then((result) => {
        return nextPromise(result);
    }).then((result) => {
        return result;
    }).catch((err) => {
        // handle err
    })
});

有人知道吗?

10 个答案:

答案 0 :(得分:1)

HTTP函数不返回承诺。他们只是发送结果。您仍然必须正确使用Promise才能发送结果,但是不需要返回值。发送响应后,HTTP函数将终止。参见documentation for more details

  

使用res.redirect(),res.send()或res.end()终止HTTP函数。

答案 1 :(得分:1)

你用你的示例代码搞定了。

Async/await 只是一种较新的承诺方式。它们可以互换使用。

这是一个相同函数的 promise 和 async/await 示例。

这个

exports.createBankAccount = functions.region('europe-west1').https.onCall((data, context) => {
    return promiseMethod().then((result) => {
        return nextPromise(result);
    }).catch((err) => {
        // handle error here
    })
});

相当于:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
  try {
    const result = await promiseMethod();
    return nextPromise(result); // You are returning a promise here
  }catch(e) {
    // handle error here
  }
});

请注意,在这两种情况下,您都在最后返回了一个承诺。这个 onCall 函数的返回值是 nextPromise(result) 的任何值。由于您正在返回 nextPromsie(result),因此您无需等待。

答案 2 :(得分:1)

要查看问题的代码解决方案,请查看 dshukertjr 的答案。

如果你想了解如何使用 async/await 返回一个“承诺链”,这里是你的答案:

你不能! 为什么 ?因为 await 用于等待 Promise 完成。一旦 await 返回一个值,他们就不再是 Promise。

因此,如果您绝对想使用 await 返回承诺,则可以等待两个返回承诺的函数之一,但不能同时等待。

这里有两种方法:

答:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    try {
        const result = await promiseMethod();
        return nextPromise(result); // You are returning a promise here
    }catch(e) {
        // handle error here
    }
});

乙:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    return promiseMethod().then(async (result) => {
        return await nextPromise(result);
    }).catch((err) => {
        // handle err
    })
});

A 和 B 的唯一区别是 A 在返回 Promise 之前等待“PromiseMethod”完成。而 B 在被调用后立即返回一个 Promise。

答案 3 :(得分:0)

似乎,我们必须以这种方式等待几个承诺:

const listOfAsyncJobs = [];
listOfAsyncJobs.push(createThumbnail(1, ...));
listOfAsyncJobs.push(createThumbnail(2, ...));
listOfAsyncJobs.push(createThumbnail(3, ...));
...
return Promise.all(listOfAsyncJobs); // This will ensure we wait for the end of the three aync tasks above.

答案 4 :(得分:0)

从异步方法返回的任何内容都会自动包装在 promise 中。 例如

const myFun = async () => {return 5}

 myFun();


// Output in the console
Promise {<fulfilled>: 5}

你可以链接返回的结果,因为它是一个承诺

其他答案中建议的增强功能的另一个示例

 const myFun4 = async () => {
      const myNum = await new Promise(r => window.setTimeout(() => r(5), 1000));
      const myNum2 = await new Promise(r => window.setTimeout(() => r(5), 1000));
      return myNum + myNum2;
    }
    myFun4().then((n) => console.log(n));
    // Output
    10

答案 5 :(得分:0)

async-await 函数的返回值为 Promisehttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#return_value

所以,您实际上所做的是返回一系列承诺。

const nextPromise = () => {
    console.log('next promise!');
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('next promise result')
        }, 3000)
    });
}

const promiseMethod = () => {
    console.log('promise!');
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('promise result');
        }, 2000)
    });
}

exports.createBankAccount = functions.https.onCall((data, context) => {
    return promiseMethod().then((result) => {
        return nextPromise(result);
    }).then((result) => {
        return result;
    }).catch((err) => {
        // handle err
        console.log(err);
    })
});


exports.createBankAccountAsync = functions.https.onCall(async (data, context) => {
    const result = await promiseMethod();
    const res = await nextPromise(result);
    return res;
});

我在 firebase 上创建了测试项目,两个函数调用都给出了相同的日志。 enter image description here

答案 6 :(得分:0)

这种情况下的解决方案是 Promise.all()

    exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    const promises = [];

    const res1 = await promiseMethod();
    const res2 = await nextPromise(res1);

    promises.push(res1);
    promises.push(res2);

    // Here's the return of the promises
    return Promise.all(promises).catch(error => console.error(error));
});

您可以在 freecodecamp.org/promise-all

上的这篇文章中找到有关 Promise 的更多信息

答案 7 :(得分:0)

由于您需要返回承诺,因此您可以创建承诺对象并在处理所有承诺后从 api 解析/拒绝(返回)您的响应。

选项 1:

exports.createBankAccount = functions.region('europe-west1').https.onCall((data, context) => {
    return new Promise(async (resolve, reject) => {
        try {
            const res1 = await promiseMethod();
            const res2 = await nextPromise(res1);
            // This will return response from api
            resolve(res2);
        }
        catch (err) {
            // Handle error here
            // This will return error from api
            reject(err)
        }
    })
});

选项 2:

exports.createBankAccount = functions.region('europe-west1').https.onCall((data, context) => {
    return new Promise(async (resolve, reject) => {
        const res1 = await promiseMethod();
        const res2 = await nextPromise(res1);
        // This will return response from api
        resolve(res2);
    })
        .then((val) => val)
        .catch((err) => {
            // Handle error here
            // This will return error from api
            return err
        })
});

答案 8 :(得分:-1)

仅在需要时转换为Promise。

即如果nextPromise返回一个Promise:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    const res1 = await promiseMethod();
    return nextPromise(res1);
});

另一方面,如果nextPromise是异步函数,只需将其转换为Promise:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    const res1 = await promiseMethod();
    return Promise.resolve(nextPromise(res1));
});

您还可以转换结果:

exports.createBankAccount = functions.region('europe-west1').https.onCall(async (data, context) => {
    const res1 = await promiseMethod();
    const res2 = await nextPromise(res1);
    return Promise.resolve(res2);
});

答案 9 :(得分:-1)

“ await”只是用于返回Promise的语法糖

编写异步函数时,代码实际上将退出该函数,并在遇到的第一个等待时返回Promise。等待之后的所有代码都将转换为then()。

因此,对于Firebase而言,使用async / await编写代码是完全可以节省的,并且根据我的经验,甚至更不容易出错,因为我可以更轻松地在代码中构造try&catch!

证明:

只需在您的控制台中运行它即可

struct User {
    var name: String!
    var age: Int!
    var hasPet: Bool!
    var pets: [Pets]!
}

struct Pets {
    var id: Int!
    var petName: String!
    var colour: String!
}

将打印:let petsFiltered = users.filter { (user) -> Bool in return (user.pets.)! }

TL; DR:您无需进行任何更改-如果您编写多次等待的代码,则将由firebase处理,就像一连串的承诺,一切都将正常工作。