Ошибка машинописи облачной функции Firebase «Не все пути кода возвращают значение» - PullRequest
0 голосов
/ 04 марта 2019

Я использую облачную функцию 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 цикла, упомянутые в ошибке, проверяют, удален продукт или нет, а продукта нет на складе или нет.Если он удовлетворяет условию, я хочу выйти из функции.Пожалуйста, помогите мне.

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Проблема глубже, чем может показаться.Возможно, вы неправильно понимаете, что делает оператор return внутри forEach.Код структурирован так, как если бы предполагалось, что он проверяет, является ли какой-либо из doc.exists ложным, и возвращает ли он раньше, если это так, но если записать его так, он вернется из обратного вызова итерации ... и поскольку forEach не используетвозвращаемое значение обратного вызова, отклонение обещания остается необработанным.

Правильными способами достижения этого результата являются следующие:

1) Просто проверьте непосредственно то, что вам нужно проверить:

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

2) Используйте цикл for..in или for..of вместо forEach:

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

3) Используйте результат map и await (не рекомендуется, поскольку выдействительно не нужно отображать):

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

Обратите внимание, что в этом случае любое отклоненное обещание внутри результирующего массива должно вызвать отклонение внешнего обещания.


Примечание:вам никогда не нужен явный вызов Promise.reject().Поскольку ваша функция асинхронная, вы можете просто throw что-то использовать в качестве ошибки - это все равно будет преобразовано в отказ от обещания.

0 голосов
/ 04 марта 2019

Сообщение об ошибке говорит вам, что есть функции, которые не возвращают значение во всех ситуациях.Это даже говорит, какие функции нарушают это требование.Вот первая ошибка:

 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 имеет значение true.Если вас не волнует эта ситуация, просто верните null:

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

Теперь ошибка исчезает, потому что все пути кода возвращают значение.Вы можете применить ту же логику к другой ошибке.

...