【问题标题】:Azure Function automatic retry on failure UnhandledPromiseRejectionWarningAzure Function 失败时自动重试 UnhandledPromiseRejectionWarning
【发布时间】:2019-04-28 08:30:13
【问题描述】:
const fetch = require('node-fetch');
let url = 'something.com';

module.exports = function(context) {
  let a = fetch(url)

  a.then(res => {
    if(res.status!=200) throw new Error(res.statusText)
    else{
      context.done(null, res.body);
    }
  });
  a.catch(err => {
      console.log(err)
      throw new Error(err)
  });

};

我有一个像上面一样调用活动函数的持久函数。我已在此活动功能上设置失败时自动重试。重试该函数需要得到一个错误。

所以在获取请求中,当我收到 404 或类似的响应时,我想抛出一个错误。但是当我从 catch 块中抛出时,会出现如下错误

UnhandledPromiseRejectionWarning:未处理的承诺拒绝。这 错误源于在异步函数内部抛出 没有 catch 块,或拒绝未处理的承诺 使用 .catch()。

函数在那里暂停并停止执行。我必须手动停止并开始执行。我该如何处理,以便函数重试?

【问题讨论】:

    标签: node.js promise azure-functions node-fetch azure-durable-functions


    【解决方案1】:

    您的代码分支。

    忽略细节,你所拥有的是:

    let a = <Promise>; // root
    a.then(...); // branch_1
    a.catch(...); // branch_2
    

    因此,当您捕获 a 中出现的错误时,分支 1 中出现的任何错误都不会被捕获。因此警告

    比较一下:

    let a = <Promise>; // root
    a.then(...).catch(...); // branch
    

    <Promise>.then(...).catch(...); // no assignment necessary
    

    所以,你可以写:

    module.exports = function(context) {
        return fetch(url)
        .then(res => {
            if(res.status!=200) {
                throw new Error(res.statusText);
            } else {
                context.done(null, res.body);
            }
        })
        .catch(err => {
            console.log(err)
            throw new Error(err)
        });
    };
    

    或者,取决于模块和调用者之间所需的职责划分......

    module.exports = function(context) {
        return fetch(url)
        .then(res => {
            if(res.status!=200) {
                throw new Error(res.statusText);
            } else {
                return res;
            }
        });
    };
    

    ...并在调用者的.then() 回调中调用.context.done(null, res.body);

    在这两种情况下,如果包含return,调用者将需要捕获错误,否则您将再次收到未处理的错误警告。

    【讨论】:

    • 我之前尝试过非分支承诺。当 catch 块抛出错误时,我得到unhandled error warning。如果没有抛出错误,我的函数将不会重新启动。调用者有没有办法在不捕获错误的情况下抛出错误? @Roamer-1888
    • 如果你没有从函数中返回 Promise,那么就不要重新抛出错误;它会被抓住并保持被抓住。如果你从函数返回 Promise 然后在 catch 块中重新抛出错误,并注意我的最后一段。
    【解决方案2】:

    发现使用async/await这个问题消失了,抛出异常后函数重试。

    const fetch = require('node-fetch');
    let url = 'something.com';
    
    module.exports = async function(context) {
    
      let res = await fetch(url)
    
      if(res.status!=200) throw new Error(res.statusText);
      else return res.body;
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多