skip to Main Content

Please I am trying to pass same object across several promises by chaining .then

I need to make an Ajax call to a php routine that request certain data from an API, part of this data would also be needed for another Ajax call to another PHP routine. This goes on across five promise .then chain

return new Promise($.ajax({
  success: function() {
    let neededObject = {}
    //add needed parts from api response to neededObject
    resolve(neededObject)
  }
}).then(neededObject => {
  //take out needed data from neededObject and make another Ajax call
  //Note that neededObject is unchanged
  return neededObject
}).then( //repeat previous step with another Api and keep returning neededObject)

This is what I intend to do, but I am getting an error that the object is undefined at the second .then
Please is there a better way to do this?

2

Answers


  1. You could explicitly pass neededObject from then to then, just like you are doing. It should work; the code snippet you submitted does not really show why it would not. Here is a proof that it does work:

    Promise.resolve("needed object")
    .then(neededObject => {
      console.log(`neededObject in then1: ${neededObject}`)
      return neededObject
    }).then(neededObject => {
      console.log(`neededObject in then2: ${neededObject}`)
      return neededObject
    }).then(neededObject => {
      console.log(`neededObject in then3: ${neededObject}`)
      return neededObject
    })

    But if that is inelegant (and I agree it is), you can make a closure over neededObject instead, like this (also changed to use Promise correctly):

    return new Promise((resolve, reject) => {
      $.ajax({
        // ...
        success: function() {
          let neededObject = {}
          // ...
          resolve(neededObject)
        }
      })
    }).then(neededObject => {
      return useNeededObject()
      .then({
        return useNeededObjectAgain()
      })
      .then({
        return useNeededObjectOnceMore()
      })
    })
    

    Alternately, you can use the fact that $.ajax returns a promise (though its own implementation of it, not the standard Promise) in order to not have to construct a Promise at all:

    $.ajax({
      // ...
    })
    .then(data => {
      let neededObject = {}
      // ...
      return neededObject
    }).then(neededObject => {
      return useNeededObject()
      .then({
        return useNeededObjectAgain()
      })
      .then({
        return useNeededObjectOnceMore()
      })
    })
    
    Login or Signup to reply.
  2. Chaining .then()s that all use the same object has a certain code smell.

    imo. these should not be chained methods, but nested. But consider an async function. Imo. this would clean up the code

    async function doSomething(){
      const response = await $.ajax({ ... });
      const neededObject = {};
      //add needed parts from api response to neededObject
    
      //take out needed data from neededObject and make another Ajax call
      await anotherApiCall
    
      //repeat previous step with another Api and keep returning neededObject
      await yetAnotherApiCall
    }
    

    and let the browser/babel worry about chaining the promises.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search