0

I have two promises

    const promise_1 = this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
      .then(ting => {
        console.log(ting);
        Dispatcher.dispatch({
        actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
        payload: ting.data.password
      })})
      .catch(error => {console.log(error)});

    const promise_2 = this.connection.getAllPatientData()
      .then( function(response) {
        console.log("Dispatrinc a new server call")
        console.log(response.data)
       Dispatcher.dispatch({
        actionType: Constants.CHANGE_ALL_PATIENTS,
        payload: response.data
      })})
      .catch(error => console.log(error))


      console.log("Done");
  }

the first one will post some data to the server, and the second one queries the data to redownload the new list. The second one is dependent on the first one. Problem is that the first promise is fulfilled after. Second promise is fulfilled first. How can I chain these two promises together so promise 2 waits on promise 1?

Shubham Yerawar
  • 660
  • 5
  • 9
bell_pepper
  • 187
  • 11
  • 1
    call this.connection.getAllPatientData() function inside then of insertPatientToDataBase function thats how we chain http calls – Ejaz Ahmed Mar 01 '19 at 12:07
  • 1
    `promise_1.then( promise_1_result => promise_2()).then( promise_2_result => { ... })` Depending if promise_2 needs the results of promise_1, you might want to use the p1 results as parameters for p2 or something and/or wrap them in another function. – Shilly Mar 01 '19 at 12:07
  • 1
    Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – Liam Mar 01 '19 at 12:10
  • You cannot chain a promise, but you can chain a function that creates a promise. – Bergi Mar 01 '19 at 12:14

4 Answers4

2

If both functions are unrelated, but promise_1 has to resolve first so that the patient exists, you can just wrap the promise creation inside a function and only call the promise_2 creation when promise_1 resolves:

const promise_1 = () => this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
  .then(ting => {
    console.log(ting);
    Dispatcher.dispatch({
    actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
    payload: ting.data.password
  })})
  .catch(error => {console.log(error)});

const promise_2 = () => this.connection.getAllPatientData()
  .then( function(response) {
    console.log("Dispatrinc a new server call")
    console.log(response.data)
   Dispatcher.dispatch({
    actionType: Constants.CHANGE_ALL_PATIENTS,
    payload: response.data
  })})
  .catch(error => console.log(error));

  promise_1().then( response => promise_2());

If promise_2 relies on the results of promise_1 to run, for example if promise_1 will return the patient id and you need that id to run promise_2 and only the result of promise_2 has to be available after both resolve, then you can modify the above a tiny bit to pass the parameter:

const promise_1 = () => this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
      .then(ting => {
        console.log(ting);
        Dispatcher.dispatch({
        actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
        payload: ting.data.password
      })})
      .catch(error => {console.log(error)});

const promise_2 = patient_id => this.connection.getAllPatientData( patient_id )
      .then( function(response) {
        console.log("Dispatrinc a new server call")
        console.log(response.data)
       Dispatcher.dispatch({
        actionType: Constants.CHANGE_ALL_PATIENTS,
        payload: response.data
      })})
      .catch(error => console.log(error));

promise_1()
  .then( patient_id => promise_2( patient_id ))
  .then( patient_data => {
    // handle patient data.
  });

You could also restructure everything into more atomic functions, so each promise has one specific goal, so you can chain them all together. If you nest the structure differently, you can even save all of the responses and return all fo then at the end.

const create_patient_id = () => this.connection.insertPatientToDataBase(Store.getPotentialPatientID());

const create_patient = patient_id => Dispatcher.dispatch({
    actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
    payload: patient_id.data.password
});

const get_patients = () => this.connection.getAllPatientData();

const update_patients = patients => Dispatcher.dispatch({
    actionType: Constants.CHANGE_ALL_PATIENTS,
    payload: patients.data
})

const workflow = () => create_patient_id()
  .then( create_patient );
  .then( get_patients )
  .then( update_patients );

 workflow();
Shilly
  • 8,511
  • 1
  • 18
  • 24
  • Confusing. In the second code block, `promise_1` and `promise_2` are functions, not promises. – Roamer-1888 Mar 01 '19 at 13:56
  • I didn't choose those names, so pretend it's `get_promise_1` and `get_promise_2`. I used the same names to not confuse the OP too much in the first and second example before I showed a renamed / refactored version. The point was that creating the promises directly, without using a function, is exactly why promise_2 resolved before promise_1 sometimes. – Shilly Mar 01 '19 at 13:59
  • `get_promise_1` and `get_promise_2` would be better. – Roamer-1888 Mar 01 '19 at 14:12
  • I prefer naming functions for what they do. I would never write something like promise_1, promise_2 in production ready code. Hence I greatly prefer the last version. – Shilly Mar 01 '19 at 14:17
1

When using then, you chain promises by creating the next one inside the previous resolver:

const promise_1 = this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
  .then(ting => {
    console.log(ting);

    Dispatcher.dispatch({
      actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
      payload: ting.data.password
    });

    return this.connection.getAllPatientData();
  })
  .then(response => {
    console.log("Dispatrinc a new server call");
    console.log(response.data);

    Dispatcher.dispatch({
      actionType: Constants.CHANGE_ALL_PATIENTS,
      payload: response.data
    });
  })
  .catch(error => {console.log(error)});

whith async/await this may be easier on the eyes:

async insertAndGet() {
  try {
    const ting = await this.connection.insertPatientToDataBase(Store.getPotentialPatientID());

    console.log(ting);

    Dispatcher.dispatch({
      actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
      payload: ting.data.password
    };

    const response = await this.connection.getAllPatientData();

    console.log("Dispatrinc a new server call");
    console.log(response.data);

    Dispatcher.dispatch({
      actionType: Constants.CHANGE_ALL_PATIENTS,
      payload: response.data
    })};
  } catch (error) {
    console.log(error);
  }
}
Markus Dresch
  • 5,290
  • 3
  • 20
  • 40
0

You can simply move second Promise into then section of the first one. If first promise fails, second one is not executed, if it resolves successfully - second one will commence. Code will look something like this:

const promise_1 = this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
  .then(ting => {
    console.log(ting);
    Dispatcher.dispatch({
      actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
      payload: ting.data.password
    });
    const promise_2 = this.connection.getAllPatientData()
      .then(response => {
        console.log("Dispatrinc a new server call");
        console.log(response.data);
        Dispatcher.dispatch({
          actionType: Constants.CHANGE_ALL_PATIENTS,
          payload: response.data
        });
    })
    .catch(console.log);
  })
  .catch(console.log);

  console.log("Done");
}

You can also chain Promises passing results from one then to another like this:

SomePromiseFunc().then(result1 => SomeOtherPromiseFunc(result1)).then(result2=> doSmth(result2)).catch();

This way could be easier if you want to use result of 1st Promise inside the second one or if catch logic is the same for both of them.

Mikhail Litvinov
  • 452
  • 2
  • 10
  • 3
    You could, but you should use promise chaining instead. – str Mar 01 '19 at 12:12
  • @str could you please provide an example for future reference pleas? I was confused to how I should chain this, given that the reference to the method for the second `then.(..` in the chain would not have the scope of the this.connection that I needed – bell_pepper Mar 01 '19 at 12:17
  • @bell_pepper I added ```Promise``` chaining with edit, it is the second example in the post now. – Mikhail Litvinov Mar 01 '19 at 12:18
  • 1
    @bell_pepper [`this.connection` is not a problem](https://stackoverflow.com/q/20279484/1048572) if you use arrow functions for your `then` callbacks – Bergi Mar 01 '19 at 12:18
-1
Promise1()
  .then(response => Promise2(response))
  .catch(err => {
    // do something with error
  });

This waits until the first promise is resolved, then calls the second promise with the result. You don't have to pass along the result, if you don't need it .then(() => Promise2()). If Promise1 fails then Promise2 is never called.

Note: Apparently I wasn't verbose enough in my initial response, so let's break it down a little better.

First, wrap your promise calls so you can provide the extra functionality to each:

class MyCustomClass {
  createNewPatient() { // maybe you pass it in? maybe it's always there?
    // Guessing Store is outside the class, but available
    return this.connection.insertPatientToDataBase(Store.getPotentialPatientID())
      .then(ting => {
        console.log(ting);
        // Guessing Dispatcher and Constants are outside the class, but available
        Dispatcher.dispatch({
          actionType: Constants.CHANGE_POTENTIAL_PATIENT_PASSWORD,
          payload: ting.data.password
        });
      })
      .catch(error => {console.log(error)});
  }

  reloadResults() {
    return this.connection.getAllPatientData()
      .then( function(response) {
        console.log("Dispatrinc a new server call")
        console.log(response.data)
        // Guessing Dispatcher and Constants are outside the class, but available
        Dispatcher.dispatch({
          actionType: Constants.CHANGE_ALL_PATIENTS,
          payload: response.data
        });
      })
      .catch(error => {console.log(error)});
  }

  // What you seem to be looking for
  createAndReload() {
    return this.createNewPatient()
      .then(() => this.reloadResults())
      .then(() => {
        console.log('done');
      });
  }
}
Steve -Cutter- Blades
  • 5,057
  • 2
  • 26
  • 40
  • Why did someone downvote this perfectly acceptable answer to the question? While it may not rewrite the original code, it does provide everything needed to resolve the issue he's trying to solve. Did I miss something critical in the question? – Steve -Cutter- Blades Mar 01 '19 at 15:52