【问题标题】:Async/Await & UnhandlePromiseRejectWarning [duplicate]Async/Await & UnhandlePromiseRejectWarning [重复]
【发布时间】:2020-06-06 16:44:22
【问题描述】:

我在 nodejs express 和 firebase 中编写了以下代码

route.js

try{
const test = await invoiceData.setAssignsInvoiced();
res.json({
      status: true,
      message: "Successful Invoice Generation"
    });
}catch (e) {
    res.status(500).json({
      status: false,
      message: "Internal Server Error",
      data: e
    });
  }

InvoicesStorage.js

setAssignsInvoiced = async() => {
    return new Promise(async (resolve,reject)=>{
        try {
            await _getAssignsForInvoiced(this);
            this.assignsForInvoiced.forEach(async assing => {
                let aux = assing._key.path.segments.length;
                let ref = assing._key.path.segments[aux - 1];
                await _updateAssignsToInvoiced(assing.data(),ref);
            });    
            resolve(true)  
        } catch (error) {
            console.error(error)
            reject(error)
        }    
    })
  };


const _updateAssignsToInvoiced = async (assing, ref) => {
  try {
    const { invoiceNum } = assing.data(); //Here's an intentional error
    await db
      .collection("leadAsign")
      .doc(ref)
      .update({
        invoiced: true,
        updateDate: Date.now() - 240 * 60 * 1000,
        invoiceNum
    });
  } catch (error) {
    console.error(error);
    throw new Error("Error at update to invoiced assigns");
  }
};

我希望它如何工作: 据我说,我应该抛出一个同步错误,因为我的代码有“等待”并停止系统。

我的答案: 代码异步运行,即在调用函数后“await”没有任何作用,并返回状态为 200 的“res.json”,并且仅在抛出下一个错误之后。

TypeError: assing.data is not a function
    at _updateAssignsToInvoiced (D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:90:35)
    at D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:55:23
    at Array.forEach (<anonymous>)
    at D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:51:37
true
POST /generateSingle 200 5182.650 ms - 57
(node:5600) UnhandledPromiseRejectionWarning: Error: Error at update to invoiced assigns
    at _updateAssignsToInvoiced (D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:102:11)
    at D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:55:23
    at Array.forEach (<anonymous>)
    at D:\$Workzone\gd_fridays_h\src\controllers\invoices\InvoicesStorage.js:51:37
(node:5600) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)
(node:5600) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

    标签: node.js firebase express async-await


    【解决方案1】:

    async/await 不起作用,因为您期望它在 forEach 循环中。此处有关于该特定问题的大量信息:https://stackoverflow.com/a/37576787/4043746

    要解决您的问题,您可以使用 for/of 循环:

    setAssignsInvoiced = async () => {
      return new Promise(async (resolve, reject) => {
        try {
          await _getAssignsForInvoiced(this)
    
          for (const assign of this.assignsForInvoiced) {
            let aux = assign._key.path.segments.length
            let ref = assign._key.path.segments[aux - 1]
            await _updateAssignsToInvoiced(assign.data(), ref)
          }
    
          resolve(true)
        } catch (error) {
          console.error(error)
          reject(error)
        }
      })
    }
    

    但是,我也很想建议返回一个承诺,因为你实际上是在这样做,因为它是一个async 函数。像这样的东西应该可以工作并且更清洁imo:

    setAssignsInvoiced = async () => {
      try {
        await _getAssignsForInvoiced(this)
    
        for (const assign of this.assignsForInvoiced) {
          let aux = assign._key.path.segments.length
          let ref = assign._key.path.segments[aux - 1]
          await _updateAssignsToInvoiced(assign.data(), ref)
        }
      } catch (error) {
        console.error(error)
        // Re-throwing the error to pass the error down, just like you've
        // done inside your _updateAssignsToInvoiced function's catch
        throw new Error('Error setting assigns')
      }
    }
    

    【讨论】:

    • 非常感谢您的建议,我还有很多需要改进的地方,您给了我很大的贡献,效果很好
    【解决方案2】:

    forEach() 循环内的异步/等待不会等到循环内的所有异步操作完成。 一种方法是像这样使用 Promise.all():

    const setAssignsInvoiced = async () => {
      try {
        await _getAssignsForInvoiced(this);
        await _updateAssignsList(this.assignsForInvoiced);
        return true;
      } catch (error) {
        console.error(error);
        return new Error(error);
      }
    };
    
    const _updateAssignsList = assignsList => {
      return Promise.all(
        assignsList.map(async assign => {
          let aux = assign._key.path.segments.length;
          let ref = assign._key.path.segments[aux - 1];
          return await _updateAssignsToInvoiced(assign.data(), ref);
        })
      );
    };
    

    我刚刚将异步循环过程提取到一个单独的函数中,该函数返回一个 Promise。

    【讨论】:

    • TY,这对我有用:D
    • 不客气。不要忘记将问题标记为已解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 2019-03-13
    • 1970-01-01
    • 2019-03-04
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多