Azure Function 失败时自动重试 UnhandledPromiseRejectionWarning

Azure Function automatic retry on failure UnhandledPromiseRejectionWarning

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

};

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

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

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().

函数在那里暂停并停止 execution.I 必须手动停止和开始执行。我该如何处理才能使函数重试?

您的代码分支。

忽略细节,你得到的是:

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,那么调用者将需要捕获错误,否则您将再次收到未处理的错误警告。

发现使用 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;

};