Implementation of simple request chain logic with promises

javascript chain promises in loop
nested promises
promise then after catch
promise chaining catch
javascript promise
es6 promise chain
promise catch
promise then return value

I'm trying to implement dummy emulation of following logic:

But I'm not sure if I fully understand best practices of how to do it. The main point of this task is to avoid triggering of redundant catch blocks callbacks. IMO if 1st request failed then all following code should stop.

I mean: if 1st request was failed, then we do not make 2nd request and do not call catch block of 2nd request promise.

In a few words I'm looking for very clean and simple solution like following:

firstRequest()
    .then(r => {
        console.log('firstRequest success', r);
        return secondRequest();
    }, e => console.log('firstRequest fail', e))
    .then(r => {
        console.log('secondRequest success', r);
        // Should I return something here? Why?
    }, e => console.log('secondRequest fail', e));

I've written following implementation. It works as expected in case of both requests are succeeded, and if 2nd request fails. But it works wrong if 1st request is failed (as you can see both catch block are triggering). You can play around with isFirstSucceed and isSecondSucceed flags to check it.

var ms = 1000;
var isFirstSucceed = false;
var isSecondSucceed = true;

var getUsersId = () => new Promise((res, rej) => {
  console.log('request getUsersId');
  setTimeout(() => {
    if (isFirstSucceed) {
      return res([1,2,3,4,5]);
    } else {
      return rej(new Error());
    }
  }, ms);
});

var getUserById = () => new Promise((res, rej) => {
  console.log('request getUserById');
  setTimeout(() => {
    if (isSecondSucceed) {
      return res({name: 'John'});
    } else {
      return rej(new Error());
    }
  }, ms);
});

getUsersId()
.then(r => {
  console.info('1st request succeed', r);
  return getUserById();
}, e => {
  console.error('1st request failed', e);
  throw e;
})
.then(
  r => console.info('2nd request succeed', r), 
  e => {
    console.error('2nd request failed', e);
    throw e;
});

Your flow diagram is the logic you want to achieve, but it isn't quite how promises work. The issue is that there is no way to tell a promise chain to just "end" right here and don't call any other .then() or .catch() handlers later in the chain. If you get a reject in the chain and leave it rejected, it will call the next .catch() handler in the chain. If you handle the rejection locally and don't rethrow it, then it will call the next .then() handler in the chain. Neither of those options matches your logic diagram exactly.

So, you have to mentally change how you think about your logic diagram so that you can use a promise chain.

The simplest option (what is probably used for 90% of promise chains) is to just put one error handler at the end of the chain. Any error anywhere in the chain just skips to the single .catch() handler at the end of the chain. FYI, in most cases, I find the code more readable with .catch() than the 2nd argument to .then() so that's how I've shown it here

firstRequest().then(secondRequest).then(r => {
    console.log('both requests successful');
}).catch(err => {
    // An error from either request will show here 
    console.log(err);
});

When you provide a catch block and you don't either return a rejected promise or rethrow the error, then the promise infrastructure thinks you have "handled" the promise so the chain continues as resolved. If you rethrow the error, then the next catch block will fire and any intervening .then() handlers will be skipped.

You can make use of that to catch an error locally, do something (like log it) and then rethrow it to keep the promise chain as rejected.

firstRequest().catch(e => {
     console.log('firstRequest fail', e));
     e.logged = true;
     throw e;
}).then(r => {
    console.log('firstRequest success', r);
    return secondRequest();
}).then(r => {
    console.log('secondRequest success', r);
}).catch(e => {
    if (!e.logged) {
        console.log('secondRequest fail', e));
    }
});

Or, a version that marks the error object with a debug message and then rethrows and can then only logs errors in one place:

firstRequest().catch(e => {
     e.debugMsg = 'firstRequest fail';
     throw e;
}).then(r => {
    console.log('firstRequest success', r);
    return secondRequest().catch(e => {
        e.debugMsg = 'secondRequest fail';
        throw e;
    });
}).then(r => {
    console.log('secondRequest success', r);
}).catch(e => {
    console.log(e.debugMsg, e);
});

I've even had situations where a little helper function saved me some code and some visual complexity, particularly if there are a bunch of these in the chain:

function markErr(debugMsg) {
    return function(e) {
        // mark the error object and rethrow
        e.debugMsg = debugMsg;
        throw e;
    }
}

firstRequest()
  .catch(markErr('firstRequest fail'))
  .then(r => {
    console.log('firstRequest success', r);
    return secondRequest().catch(markErr('secondRequest fail'));
}).then(r => {
    console.log('secondRequest success', r);
}).catch(e => {
    console.log(e.debugMsg, e);
});

Taking each of your questions individually:

How to implement described logic according to all promises best practices?

Described above. I'd say the simplest and best practice is the very first code block I show. If you need to make sure when you get to the final .catch() that you have a uniquely identifiable error so you know which step caused it, then modify the rejected error in each individual function to be unique so you can tell which it was from the one .catch() block at the end. If you can't modify those functions, then you can wrap them with a wrapper that catches and marks their error or you can do that inline with the markErr() type solution I showed. In most cases, you just need to know there was an error and not the exact step it occurred in so usually that isn't necessary for every step in the chain.

Is it possible to avoid throw e in every catch block?

That depends. If the error objects are already unique, then you can just use one .catch() at the end. If the error objects are not unique, but you need to know which exact step failed, then you have to either use a .catch() at each step so you can mark the error uniquely or you need to modify each function in the chain to have a unique error.

Should I use es6 Promises?

Yes. No better way I know of.

Or it is better to use some promises library?

I'm not aware of any features in a promise library that would make this simpler. This is really just about how you want to report errors and whether each step is defining a unique error or not. A promise library can't really do that for you.

Any other advice?

Keep learning more about how to mold promises into a solution for each individual problem.

Implementation of simple request chain logic with promises, I mean: if 1st request was failed, then we do not make 2nd request and do not call catch block of 2nd request promise. In a few words I'm  npm install request request-promise With the dependencies installed, you can make your first request. All this does is set up a GET request to the GitHub API, without any authorization, and very


IMO, you can use async/await... Still, with promises but is much cleaner to look at. Here is my sample approach on above logic.

function firstRequest() {
   return new Promise((resolve, reject) =>  {
       // add async function here
       // and resolve("done")/reject("err")
    });
 } 

function secondRequest() {
   return new Promise((resolve, reject) =>  {
       // add async function here
       // and resolve("done")/reject("err")
    });
}

async function startProgram() { 
   try { 
       await firstRequest();
       await secondRequest();
   } catch(err) { 
       console.log(err); 
       goToEndFn();
   }
}

startProgram(); // start the program

Untangling Deeply-Nested Promise Chains, The following code is a so-called “basic” example of how use Service Worker to The event object calls respondWith() and passes it a promise chain that It attempts to find a matching request in the cache. However, in the case of our Service Worker fetch example, there is a distinct fork in the logic that  One of the great things about using promises is chaining. Chaining. A common need is to execute two or more asynchronous operations back to back, where each subsequent operation starts when the previous operation succeeds, with the result from the previous step. We accomplish this by creating a promise chain.


https://github.com/xobotyi/await-of

$ npm i --save await-of 

import of from "await-of";

async () => {
    let [res1, err1] = await of(axios.get('some.uri/to/get11'));
    let [res2, err2] = await of(axios.get('some.uri/to/get22'));

    if (err1) {
       console.log('err1', err1)
    }
    if (err2) {
       console.log('err2', err2)
    }
    console.log('res1', res1)
    console.log('res2', res2)

};

Promise Chaining in JavaScript, In this tutorial, you will learn about the promise chaining pattern that chains promises to execute Introduction to the JavaScript promise chaining Therefore, you can call the promise's instance method on the return Promise . Unary Operators · Assignment Operators · Logical Operators · Comparison Operators  On an Observable object, RxJS toPromise() method is called which converts the observable to Promise object. On the Promise object, the method then is invoked which returns the Promise<Rx[]>. The code below represents the processing of callee method which returns Promise<Rx[]>.


Async/await maybe?

async function foo() {
    try {
        const firstResult = await firstRequest();
        const secondResult = await secondRequest();
    } catch(e) {
        // e = either first or second error
    }
}

In this code an error on the first request transfers control to the catch block and the second request won't start

Should I use es6 Promises?

Probably yes, until you're pretty sure your code will be used in obsolete environments. They are already not so new and flashy

Promises chaining, Let's return to the problem mentioned in the chapter Introduction: callbacks: we The whole thing works, because a call to promise.then returns a promise, covered in separate chapters, but the basic syntax is quite simple:. Renamed internally used package @request/promise-core to request-promise-core because there where too many issues with the scoped package name (Thanks to @cabrinoob, @crazy4groovy, @dsandor, @KpjComp, @lorenwest, @Reisyukaku, @tehChromic, @todd for providing helpful information.)


you do not need handle error for every promise

you need handle error only as common error

do like this:

var ms = 1000;
var isFirstSucceed = false;
var isSecondSucceed = true;

var getUsersId = () => new Promise((res, rej) => {
  console.log('request getUsersId');
  setTimeout(() => {
    if (isFirstSucceed) {
      return res([1,2,3,4,5]);
    } else {
      return rej();
    }
  }, ms);
});

var getUserById = () => new Promise((res, rej) => {
  console.log('request getUserById');
  setTimeout(() => {
    if (isSecondSucceed) {
      return res({name: 'John'});
    } else {
      return rej(new Error());
    }
  }, ms);
});

getUsersId()
.then(r => {
  console.info('1st request succeed', r);
  return getUserById();
})
.then(r => {
  console.info('2st request succeed', r);
  return;
})
.catch((e) => {
    console.error('request failed', e);
    throw new Error(e);
})

How to manage Promises into dynamic queue with vanilla JavaScript, How can we conduct its way through our application. We need to somehow coordinate all promises, to chain promises dynamically in order to Basic queue implies that each task happens one after another, plus their calling order Let's create a separate file which holds all the logic related to our task. To keep the promise chain going, you can't use setTimeout() the way you did because you aren't returning a promise from the .then() handler - you're returning it from the setTimeout() callback which does you no good. Instead, you can make a simple little delay function like this:


Error handling in long Promise chains - Arthur Xavier, if you make use of some complex business logic to access those microservices​. In my case I was developing a giant form for a web application using AngularJS. Simple, efficient and pretty, although naive; this was the code for the Where all the functions on the Promise chain such as uploadImage,  A promise implementation that also allows you to wrap your object's API with promise-like API: 1.0: sure-thing: A simple and fast Promises/A+ implementation. 1.1: Taxi: Simple and Annotated. A tiny example Promises/A+ implementation. Just for learning. 1.1: Ten.Promise: Promises/A+ implementation written in TypeScript: 1.0: then/promise


How JavaScript promises actually work from the inside out, Looks like a simple function with some properties initialized to 0 or null . Let's move on to the definition of doResolve and see how it's implemented. These arguments contain logic on how resolve or reject should be called. _deferredState = 1 , and for the chain of promises, it will call handle() for each  @domenic great post!. I maintain underscore.deferred, a standalone implementation of jQuery Deferreds that works as an underscore mixin.I had been intrigued by your post and finally got around to making my implementation pass your test suite (the promises part anyway, still failing 2 of the "always-async" tests), but it raised some questions along the way.


Write Better JavaScript with Promises, Like the callback example, this appends the result of the API request to the result of a promise and pass it to the next handler in the chain. Then, it was as simple as writing {{ hipsterIpsum.text }} in a template. But the ultimate win, imho​, is simply that your application logic becomes far more readable. Javascript Promise Best Practices & Anti-Patterns. Tagged with javascript, promises, es6, errors.