Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining promises with promises inside then()

How do you chain in an scenario like this?

api is a function that returns a promise after an http request. auth is a function that returns a promise after api respond, if resolves api is called for a second time, if not auth rejects.

I tried this, but not only am I going back to the callback hell, it does not work.

function api(query) {
   return new Promise(function(resolve, reject) {
     //DO SOME STUFF AND SOMETIMES resolves...
   })
}

function auth() {
   return new Promise(function(resolve, reject) {
     api("/foo").then(function(asset1) {
        api("/bar").then(function(asset2) {
           resolve(asset2);
        }).catch(function() {
           reject();
        })
     }).catch(function(error) {
        reject();
     })

   })
}
like image 205
DomingoSL Avatar asked Jan 03 '17 13:01

DomingoSL


3 Answers

As far as i understand what you are trying to do, following code will also resolve with asset2. Besides that i guess api function is doing http request so you could benefit from using request-promise lib instead of converting callback api with new Promise thing.

function api(query) {
   return new Promise(function(resolve, reject) {
     //DO SOME STUFF AND SOMETIMES resolves...
   })
}

function auth() {
   return api("/foo")
   .then(() => api("/bar"))
}

With this caller would do something like:

auth()
.then(asset2 => ...)
.catch(err => ...)

If order of calling api is not important, like @styfle pointed out in comment, you could write it using Promise.all

function auth () {
  return Promise.all([
    api("/foo"),
    api("/bar")
  ])
}
like image 177
Srle Avatar answered Oct 23 '22 11:10

Srle


A cleaner way to do it:

return myFirstPromise.then( (returnFromFirst) => {
    //Do something
    return secondPromise();
}).then( (returnFromSecond) => {
    //Do something
    return thirdPromise();
}).then( (returnFromThird) => {
    //All Done
}).catch( (e) =>{}
    console.error("SOMETHING WENT WRONG!!!");
);
like image 22
Amritansh Avatar answered Oct 23 '22 11:10

Amritansh


I think this should help you.

Just an observation: then method always return a promise based on the previous promise resolution. If the previous promise is resolved it will pass the resolved value to the next promise. Otherwise it will send the error to the catch method.

function auth () {
  /*
    Since `then` already returns a new Promise, 
    you don't need to create a new Promise.
  */
  return api('/foo').then(function (asset1) {
    return api('/bar')
  })
}

/*
  So you can call auth:
*/

auth().then(function (asset2) {
  console.log('This is my asset2:', asset2)
}).catch(function (error) {
  console.error('Error', error)
})
like image 7
Rômulo M. Farias Avatar answered Oct 23 '22 11:10

Rômulo M. Farias