【问题标题】:Error: Function returned undefined, expected Promise or value错误:函数返回未定义、预期的 Promise 或值
【发布时间】:2019-11-18 02:47:45
【问题描述】:

我设置了一个带有 firebase 函数的 pubsub 函数,以便经常在 Firestore 中执行一些操作。为此,我需要向第三方 API 发出请求以获取更新的数据,然后我想将该数据插入到 Firestore 中正确的集合和文档中。

const request_promise = require('request-promise')

exports.scheduledFunction = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
    console.log('This will be called every 2 minutes')
    var username = ''
    var password = ''
    var options = {
        url: 'path.to.api.com',
        auth: {
            user: username,
            password: password
        },
        json: true
    }

    request_promise(options)
        .then(function (product) {
            console.log(product.product_id)
            db.collection('products').doc(product.product_id).set(product)
                .then(() => {
                    console.log('Document successfully written')
                })
                .catch(error => {
                    console.log('Error writing product to firestore', error)
                })
        })
        .catch(function (err) {
            console.log('Failed to get product', error)
        })
  });

在上面的代码中,如果我注释掉将数据添加到 Firestore 的调用,我会将正确的 product_id 打印到控制台,因此我知道请求正在运行,但如果将其留在我得到“函数返回未定义,预期的承诺”或价值'。

【问题讨论】:

  • require('request_promise') 将是 require('request-promise')
  • 您需要返回一个在所有异步工作完成后解决的承诺。现在,您忽略了 request_promise()db.collection().doc().set() 返回的承诺。您将需要学习如何有效地使用 JavaScript Promise,以便让 Cloud Functions 执行您想要的操作。
  • 另外,request_promise(options).then(..)return request_promise(options).then(..)

标签: node.js firebase express google-cloud-firestore google-cloud-functions


【解决方案1】:

通过适当的承诺链,这看起来更干净

      rp(options)
        .then((product) =>
        {
            console.log(product.product_id)
            // add an implicit return here
            return db.collection('products').doc(product.product_id).set(product)
        })
        .then(() =>
        {
            console.log('Document successfully written')
            // need's to return something here, using a boolean for simplicity
            return true;
        })
        .catch(function (err) 
        {
        console.log('Failed to get product', error);
        // throw will exit the function call
        throw Error('Failed to get product', error);
        });

另外,不建议从 catch 块中抛出错误,catch 块是为了捕获错误并处理它们,而不是抛出错误。您的代码中有一些地方需要改进,但这不是这个问题的一部分

干杯, 快乐编码

【讨论】:

    【解决方案2】:

    您在执行时不会返回任何东西。 console.log 不被视为 return

    request_promise(options)
            .then(function (product) {
                console.log(product.product_id)
                // add an implicit return here
                return db.collection('products').doc(product.product_id).set(product)
                    .then(() => {
                        console.log('Document successfully written')
                        // need's to return something here, using a boolean for simplicity
                        return true;
                    })
                    .catch(error => {
                        console.log('Error writing product to firestore', error)
                        // throw will exit the function call
                        throw Error('Error writing product to firestore', error);
                    })
            })
            .catch(function (err) {
                console.log('Failed to get product', error);
                // throw will exit the function call
                throw Error('Failed to get product', error);
            })
    

    【讨论】:

    • 这仍然忽略了调用 Firestore 返回的承诺。
    • @DougStevenson 不确定这是否会有所不同,但我在第一个执行的then 中使用return 对其进行了编辑。
    • @DougStevenson 我的印象是“then”块是调用 Firestore 返回的承诺
    • 它还返回了另一个承诺。就像抓住一样。它们都是异步的。你不能把一个异步函数变成一个同步函数。
    • 我认为 Promise 链接不正确,这就是为什么不维护调用顺序
    猜你喜欢
    • 2018-04-18
    • 2018-12-03
    • 2019-08-12
    • 1970-01-01
    • 2018-09-27
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2018-12-05
    相关资源
    最近更新 更多