简体   繁体   中英

JS: Complex Promise chaining

I'm faced with a small issue when trying to chain complex function calls with Promises and callbacks.

I have a main function, which calls subroutines. In these routines API calls are made.

For Example:

function handle(){
    new Promise(function(resolve, reject){
        let result = doAPICall1()
        if (result === true) resolve(true);
        reject(JSON.stringify(result))
    }).then(function(){
        let result = doAPICall2()
        if (result === true) return true
        throw new Error(JSON.stringify(result))
    }).catch(error){
        console.error(JSON.stringify(error))
    }
}
function doAPICall1(){
    axios.get('...').then(function(){
        return true
    }).catch(function(error){
        return error
    })
}

function doAPICall2(){
    axios.get('...').then(function(){
        return true
    }).catch(function(error){
        return error
    })
}

But when I execute this example, doAPICall2 will be executed, while doAPICall1 is still running.
It only occures when long running calls are made.

Does anyone can give me a hint? Thank you!

Don't worry and take some time to understand Promises better. In the example code below, doAPICall function return a Promise which resolves to a value, not the value itself.


    function handle() {
        doAPICall().then(result => {
            //do something with the result
        }).catch(error => {
            //catch failed API call
            console.error(error)
        }) 
    }

    doAPICall() {
        // this returns a Promise
        return axios.get(...)
    }

You're overdoing manually a lot of things that Promises already do for you: axios.get already returns a Promise, so there is no point in return a the response when it resolves and return a false when it rejects. A catch handler at the end of a Promise chain already handles all errors that may arise during the chain, so you don't need to catch every Promise.

I would do something like:

function doAPICall1(){
  return axios.get('...');
}

function doAPICall2(){
  return axios.get('...');
}

function handle(){
  // in case you would use the api calls results.
  let firstResult = null;
  let secondResult = null;
  return doAPICall1()
  .then(res => {firstResult = res})
  .then(() => doAPICall2())
  .then(res => {
    secondResult = res;
    return []
   })
}

I guess you will use the Api calls results for something. With the code above, you could consume the handle() function like follows:

function someSortOfController(){
  handle().then(results => {
    console.log(results[0]); // first api call result
    console.log(results[1]); // second api call result
  })
  .catch(err => {
    // here you will find any error, either it fires from the first api call or from the second.
    // there is *almomst* no point on catch before
    console.log(err);
  })
}

There, you will access any error, either it came from the first api call or the second. (And, due to how Promises work, if the first call fails, the second won't fire).

For more fine grained error control, you may want to catch after every Promise so you can add some extra logs, like:

function doAPICall1(){
  return axios.get('...')
  .catch(err => {
    console.log('the error came from the first call');
    throw err;
  });
}

function doAPICall2(){
  return axios.get('...')
  .catch(err => {
    console.log('the error came from the second call');
    throw err;
  });
}

Now, if the first api call fails, everything will work as before (since you're throwing the error again in the catch ), but you have more control over error handling (maybe the error returning from API calls is not clear at all and you want this kind of control mechanism).

Disclaimer

This answer doesn't answer why your code acts like it does. However, there are so much things wrong in your code, so I think providing you with an example about using Promises is more valuable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM