【问题标题】:Firebase cloud function typescript error "Not all code paths return a value"Firebase 云函数打字稿错误“并非所有代码路径都返回值”
【发布时间】:2019-07-25 08:54:29
【问题描述】:

我正在使用 firebase 云功能和 firestore 交易来减少基于购买的产品的可用数量。部署时返回错误“错误 TS7030:并非所有代码路径都返回值”

这里是代码

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';


admin.initializeApp();
const db = admin.firestore()

exports.newOrder = functions.firestore
.document('orders/{orderId}')
.onCreate(async (snap, context) => {

    try {
        const data = snap.data();
        if (data === undefined) return null

        const itemList = data.list as Array<any>
        const productId: Set<string> = new Set<string>();

        itemList.forEach((item) => {
            productId.add(item.id)
        })
        return db.runTransaction(async t => {

            const promises: Promise<admin.firestore.DocumentSnapshot>[] = []
            productId.forEach(i => {
                const p = admin.firestore().doc('Products/' + i).get()
                promises.push(p)
            })
            const docs=await Promise.all(promises)
            docs.forEach(doc => {
                if (!doc.exists) {
                    return Promise.reject("Product deleted")
                }
            })
            itemList.forEach(j => {
                if (j.variation === '-') {
                    const available = docs[j.id].get('available')
                    const needed = j.quantity
                    if (available < needed) {
                        return Promise.reject("Product out of stock")
                    }
                }
                else {
                    const variations = docs[j.id].get('variation') as Map<string, any>
                    for (const i in variations.keys) {
                        if (i === j.variation) {
                            const needed = j.quantity
                            const available = docs[j.id].get('variation').get(i).get('quantity')
                            if (available < needed) {
                                return Promise.reject("Product out of stock")
                            }
                        }
                    }
                }
            })
            itemList.forEach(j => {
                if (j.variation === '-') {
                    const available = docs[j.id].get('available')
                    const needed = j.quantity
                    t.update(db.doc('Products/' + j.id), { 'available': available - needed })
                }
                else {
                    const variations = docs[j.id].get('variation') as Map<string, any>
                    for (const i in variations.keys) {
                        if (i === j.variation) {
                            const needed = j.quantity
                            const available = docs[j.id].get('variation').get(i).get('quantity')
                            t.update(db.doc('Products/' + j.id), { [`variation.${i}.quantity`]: available - needed })
                        }
                    }
                }
            })
            return Promise.resolve("Product quantity updated")
        })
    }
    catch (error) {
        console.log(`error ${error}`)
        return null
    }
});

这是部署中显示的错误

 src/index.ts:30:30 - error TS7030: Not all code paths return a value.

 30                 docs.forEach(doc => {
                            ~~~~~~~~

 src/index.ts:35:34 - error TS7030: Not all code paths return a value.

 35                 itemList.forEach(j => {
                                ~~~~~~


 Found 2 error 

如何解决错误。

错误中提到的2个循环检查产品是否被删除以及产品是否缺货。如果它满足我想退出函数的条件。请帮帮我。

【问题讨论】:

    标签: typescript google-cloud-firestore google-cloud-functions tslint


    【解决方案1】:

    这是 Typescript 强加愚蠢约定的一个很好的例子。 当没有明确的 return 语句时,JavaScript 函数默认输出undefined。我建议在tsconfig.json 中禁用退货检查:

    {
      "compilerOptions": {
        "noImplicitReturns": false,
      }
    }
    

    【讨论】:

      【解决方案2】:

      问题比看起来更深。您可能误解了return 语句在forEach 中的作用。代码的结构好像假设检查任何doc.exists 是否为假,如果是则提前返回,但写成这样,它将从迭代回调中返回......并且由于forEach 不使用回调返回值,承诺拒绝仍然未处理。

      实现此结果的正确方法如下:

      1) 直接检查你需要检查的:

      if (docs.findIndex(doc => !doc.exists) !== -1) {
          return Promise.reject("Product deleted");
      }
      

      2) 使用for..infor..of 循环而不是forEach

      for (doc of docs) {
          if (!doc.exists) {
              return Promise.reject("Product deleted")
          }
      }
      

      3) 使用mapawait 的结果(不推荐,因为你并不真的需要映射):

      await Promise.all(docs.map(doc => {
          if (!doc.exists) {
              return Promise.reject("Product deleted")
          }
          return null
      })
      

      请注意,在这种情况下,结果数组中的任何被拒绝的 Promise 都应该触发外部 Promise 的拒绝。


      旁注:您永远不需要明确的Promise.reject() 调用。由于你的函数是异步的,你可以简单地 throw 一些你将用作错误的东西 - 这无论如何都会转化为承诺拒绝。

      【讨论】:

        【解决方案3】:

        错误消息告诉您,有些函数在所有情况下都不会返回值。它甚至可以告诉哪些功能违反了这个要求。这是第一个错误:

         src/index.ts:30:30 - error TS7030: Not all code paths return a value.
        
         30                 docs.forEach(doc => {
                                    ~~~~~~~~
        

        它告诉你你传递给 forEach 的函数有问题。

        函数如下:

                docs.forEach(doc => {
                    if (!doc.exists) {
                        return Promise.reject("Product deleted")
                    }
                })
        

        请注意,当doc.exists 为真时,该函数不会返回值。如果你不关心这种情况,直接返回null即可:

                docs.forEach(doc => {
                    if (!doc.exists) {
                        return Promise.reject("Product deleted")
                    }
                    else {
                        return null
                    }
                })
        

        现在错误消失了,因为所有代码路径都返回了一个值。您可以将相同的逻辑应用于其他错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-01
          • 2014-04-16
          • 2015-02-07
          • 2012-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多