Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error handling in Javascript promise

I have some Javascript code doing some asyncronous stuff with some synchronouse post processing and then asyncronous stuff again (XHR -> parse XHR -> new XHR based on the first one). I don't get the error handling done:

/* API */
function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        return data.id
    }, handleError)
}

function handleError(errorObj) {
    if (errorObj.status) {
        return errorObj.status
    } else {
        return errorObj
    }
}

function myApiCall() {
    return getFile(1)
        .then(getFile, handleError)
        .then(getFile, handleError)
        .then(getFile, handleError)
        .then(getFile, handleError);
}


/* caller */

function failFunction(status) {
    console.log("fail: ")
    console.log(status)
}

myApiCall().then(function(id) {
        console.log(id)
    }, failFunction)

1.json looks something like this

{
    "id": "2"
}

Just referencing the next file, the other ones are equivalent.

Until here everything is fine (even I'm not sure if that's the best way to do errorhandling). If all files exist, the success function of the caller is called, otherwise the error function.

But when having some errors in my synchronous code, everthing breaks

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        throw new Error(42) //       <---------
    }, handleError)
}

Now I get a console output

Error: 42

No further processing, caller is not informed.

I tried something like that

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        throw new Error(42)
    }, handleError)
    .catch(handleError)
}

But this doesn't make anything better. Mostly of all I get a TypeError: $.ajax(...).then(...).catch is not a function

How is error handling solved correct in this case?

like image 459
mibutec Avatar asked Nov 28 '15 04:11

mibutec


1 Answers

Because you are handling errors at every stage, and not propagating them, then you will end up with the problems you are having

edit:

The above statement is wrong, I didn't realise how broken jquery promises are when I wrote it - see the difference between the first block of code (Promise/A+) and the second (jQuery promise with fingers crossed behind it's back)

instead you can do something like:

function getFile(name) {
  // wrap jquery "promise" in real Promise
  // you'll need a Promise polyfill for Internet Explorer to use this method
  return new Promise(function(resolve, reject) {
    $.ajax({
      url: name + ".json?" + Math.random()
    }).then(function(data) {
      resolve(data.id);
    }, function(err) {
      reject(err);
    });
  });
}

function handleError(errorObj) {
  //console.log(errorObj)
  if (errorObj.status) {
    throw errorObj.status;
  } else {
    throw errorObj;
  }
}

function myApiCall() {
  return getFile(1)
  .then(getFile)
  .then(getFile)
  .then(getFile)
  .then(getFile)
  .catch(handleError);
}

function failFunction(status) {
  console.log("fail: ")
  console.log(status)
}

myApiCall().then(function(id) {
  console.log(id);
})
.catch(failFunction);

When using jQuery, whose promises are like promises you make with your fingers crossed behind your back

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        return data.id;
    });
}
function handleError(errorObj) {
    if (errorObj.status) {
        return errorObj.status; // return in jquery!
    } else {
        return errorObj;
    }
}
function myApiCall() {
    return getFile(1)
        .then(getFile)
        .then(getFile)
        .then(getFile)
        .then(getFile)
        .fail(handleError); // like jquery promises in general, use fail instead of the compliant catch
}
/* caller */
function failFunction(status) {
    console.log("fail: ");
    console.log(status);
}
myApiCall().then(function(id) {
    console.log(id);
})
.fail(failFunction);
like image 145
Jaromanda X Avatar answered Sep 21 '22 21:09

Jaromanda X