Firebase cloud function typescript error “Not all code paths return a value”

前提是你 提交于 2021-01-27 23:48:39

问题


I am using firebase cloud function and firestore transaction to decrease the available quantity of product based on purchases. At the time of deploy it returns the error "error TS7030: Not all code paths return a value"

Here is the code

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
    }
});

Here is the error shown in deploy

 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 

How to solve the error.

2 loops mentioned in the error checks whether the products is deleted or not and product is out of stock or not. If it satisfies the condition i want to exit from the function. Please help me.


回答1:


The probles is deeper than it may seem to be. You're possibly misunderstanding what does return statement do inside the forEach. The code is structured as if it was assumed to check if any of the doc.exists is false and return early if so, but written as this, it will return from the iteration callback.. and since forEach doesn't use the callback return value, the promise rejection remains unhandled.

The proper ways of achieving this result would be the following:

1) Just check directly what you need to check:

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

2) Use the for..in or for..of loop instead of forEach:

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

3) Use the map and await the result (not recommended, since you don't really need mapping):

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

Note that in this case any rejected promise inside the resulting array should trigger the rejection of the outer promise.


Side note: you don't ever need the explicit Promise.reject() call. As your function is async, you can simply throw something you'll use as an error - this will be transformed into promise rejection anyway.




回答2:


The error message is telling you that there are functions that don't return a value in all situations. It's even telling which functions are violating this requirement. Here's the first error:

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

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

It's telling you that the function you're passing to forEach is having a problem.

Here's the function:

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

Note that the function isn't returning a value when doc.exists is true. If you don't care about this situation, just return null:

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

Now the error goes away, because all code paths return a value. You can apply the same logic to the other error.



来源:https://stackoverflow.com/questions/54976561/firebase-cloud-function-typescript-error-not-all-code-paths-return-a-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!