如何解决您的函数被杀死,因为它在我的 Firebase 模拟器中引发了未处理的错误?

问题描述

我正在尝试使用 Firebase 模拟器运行下面的 Firestore 触发器代码firebase emulators:start

如您所见,在 firestore 触发器内部,我有一个代码可以删除存储在 Firebase Storage 中的图像

我的代码

exports.onDelete = functions
.firestore.document(path)
.onDelete((snapshot,context) => {

    try {

        const deletedUser = new User(snapshot.data());
        const promise1 = db.doc(`devices/${deletedUser.uid}`).delete();

        // deleting the image in Storage
        const defaultBucket = storage.bucket();
        const profilePictureFile = defaultBucket.file(`profilePicture/${deletedUser.uid}`);
        const promise2 = profilePictureFile.delete();

        const promises: Promise<any>[] = [promise1,promise2];
        return Promise.all(promises);

    } catch (error) {
        console.log(error);
        return Promise.reject(error);
    }
    

});

因为 Firebase 模拟器目前没有用于存储的模拟器,所以我预计会出现错误

但是我有这样的警告

enter image description here

正如你在最底部看到的,有一个警告说

您的函数被终止,因为它引发了未处理的错误

这是一个严重的错误吗?我的意思是,我想我已经在我的代码中提供了 try catch 块,但为什么它仍然被视为未处理的错误?如何解决这个问题?

抱歉,我是 Node 初学者,我是移动开发人员。所以如果我的问题有点傻,我很抱歉

解决方法

当您没有捕获由 Promise 生成的错误时,就会被视为未处理的错误。看起来您正在尝试删除一个不存在的对象,因此它抛出了一个您没有在 Promise.all 调用中捕获的错误。

要修复您的代码而不对其进行实质性更改,只需在您的 .catch() 调用中添加一个 Promise.all()

Promise.all(promises)
  .catch(() => console.error("Oh no,an error occurred!"));

简而言之,promise 应始终至少附加以下功能之一:.then().catch().finally()

myFunction.doSomethingReturnPromise();

myFunction.doSomethingReturnPromise().then();

另一个重要的点是 Promise.all() 是全有或全无,这意味着如果一个 promise 失败,它会立即退出。如果文件不存在,您应该单独运行每个 promise,否则您需要创建包装函数来删除始终解析的文件。

也不要将所有代码都包装在 try/catch 中,而是单独处理每个操作。但是我假设您实际上并不关心它是否成功,对吗?

以下是我将如何编写此函数:

/**
 * Generic delete funcion that will call .delete() on storage objects or database nodes
 * @param doc
 */
const deleteObj = (doc) => {
    return new Promise((resolve: null) => {
        // Delete and resolve no matter what
        doc.delete()
            .finally(() => resolve());
    });
};

exports.onDelete = functions.firestore.document(path).onDelete((snapshot,context) => {
    const deletedUser = new User(snapshot.data());
    const defaultBucket = storage.bucket();

    // Since both types of objects have a similarly named .delete() function,we can use the same function
    // to delete them
    const promises = [
        deleteObj(db.doc(`devices/${deletedUser.uid}`)),deleteObj(defaultBucket.file(`profilePicture/${deletedUser.uid}`))
    ];

    Promise.all(promises)
      .finally(() => console.log("All done"));
});

注意:在我修改后的代码中,由于对 Promise.all() 的所有承诺都保证会解决,因此我不需要添加 .catch() 或将其包装在 try/catch 中。>