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

};

I have a durable function that calls an activity function like above. I have set automatic retry on failure on this activity function. To retry the function needs to get an error.

So In get request I want to throw an error when i get response like 404 or something similar. But when i throw from catch block i get an error like below

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

function pauses there and stops execution.I have to manually stop and start the execution. How can i handle this so that the function retries?

Nafis Islam
  • 1,483
  • 1
  • 14
  • 34

2 Answers2

1

Your code branches.

Ignoring the detail, what you have is :

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

So whereas you catch errors arising in a, any error arising in branch 1 will be uncaught. Hence the warning

Compare that with :

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

or

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

So, you might write :

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

Alternatively, depending on the required division of responsibilities between module and caller(s) ...

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

... and call .context.done(null, res.body); in a .then() callback in the caller.

In both cases, with return included, then the caller will need to catch errors otherwise you will again get an unhandled error warning.

Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • I tried the non branching promise before. When the catch block throws the error i get `unhandled error warning`. With out throwing error my function will not re-start. Is there no way for the caller to throw error with out catching it? @Roamer-1888 – Nafis Islam Nov 26 '18 at 17:27
  • 1
    If you don't return Promise from the fnction, then simply don't re-throw the error; it will be caught and stay caught. If you return Promise from the function then re-throw the error in the catch block, and heed my last paragraph. – Roamer-1888 Nov 26 '18 at 17:36
0

Found that with the use of async/await this problem goes away and the function re-try after exception is thrown.

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;

};
Nafis Islam
  • 1,483
  • 1
  • 14
  • 34