Автоматическая повторная попытка функции Azure при сбое 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)
  });

};

У меня есть прочная функция, которая вызывает функцию активности, как указано выше. Я установил автоматическую повторную попытку при сбое для этой функции действия. Чтобы повторить попытку, функция должна получить ошибку.

Итак, в запросе получения я хочу выдать ошибку, когда получаю ответ типа 404 или что-то подобное. Но когда я выхожу из блока catch, я получаю сообщение об ошибке, как показано ниже

UnhandledPromiseRejectionWarning: необработанное отклонение обещания. Эта ошибка возникла либо из-за вызова асинхронной функции без блока catch, либо из-за отклонения обещания, которое не было обработано с помощью .catch ().

функция приостанавливается и останавливает выполнение. Мне нужно вручную остановить и начать выполнение. Как я могу справиться с этим, чтобы функция повторила попытку?


person Nafis Islam    schedule 26.11.2018    source источник


Ответы (2)


Ваш код ветки.

Не обращая внимания на детали, у вас есть:

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

Таким образом, в то время как вы обнаруживаете ошибки, возникающие в a, любая ошибка, возникающая в ветви 1, не будет обнаружена. Следовательно, предупреждение

Сравните это с:

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

or

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

... и вызовите .context.done(null, res.body); в .then() обратном вызове вызывающей стороны.

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

person Roamer-1888    schedule 26.11.2018
comment
Раньше я пробовал использовать обещание без ветвления. Когда блок catch выдает ошибку, я получаю unhandled error warning. Без выброса ошибки моя функция не будет перезапущена. У вызывающего абонента нет возможности выдать ошибку, не уловив ее? @ Roamer-1888 - person Nafis Islam; 26.11.2018
comment
Если вы не вернете Promise из функции, просто не вызывайте ошибку повторно; он будет пойман и останется пойманным. Если вы вернете Promise из функции, то повторно выбросите ошибку в блоке catch и обратите внимание на мой последний абзац. - person Roamer-1888; 26.11.2018

Обнаружено, что с использованием 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;

};
person Nafis Islam    schedule 04.12.2018