Search code examples
javascriptpromisees6-promise

How to work with promise chains if the subsequent promises will be returned based on the condition?


We have a requirement where I need to run API-1. If it succeeds and the result of the API response is 'true', I need to run API-2, If it succeeds and the result of API response is 'true', I need to run API-3. I tried to use promise chain as below.

runMethodGeneric('A').then((data, status, xhr) => {
    if(xhr.status === 200) {
        if(data.result === 'true') {
            runGenieMethodGeneric('B');
        } else {
            console.log('A result is false');
        }
    }
}).then((data, status, xhr) => {
    console.log(data);
    if(xhr.status == 200) {
        if(data.result === 'true') {
            runGenieMethodGeneric('C');
        } else {
            console.log('B result is false');
        }
    }
}).then((data, status, xhr) => {
    console.log(data);
    if(xhr.status === 200) {
        if(data.result === 'true') {
            console.log('C result is true');
        } else {
            console.log('C result is false');
        }
    }
}).catch((jqXhr, textStatus, errorMessage) => {
    console.log(errorMessage);      
});

runMethodGeneric is a generic method to run all the APIs and it is defined as below.

function runMethodGeneric(method) {
    let url = 'http://192.168.1.253:55678/cl';

    const json = {
        user_data: data,
        params: [],
        gene_method: method,
        requestedAction: 'RUN_GENIE_METHOD'
    };

    let jsonStr = JSON.stringify(json);

    return $.ajax(url, {
        type: 'POST',
        dataType: 'JSON',
        data: jsonStr,
    });
}

I am using 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js' in html for jquery.

First API call 'A' is working and control is hitting first 'then' block and second API call 'B' is executed. when control hits second 'then' block, data, status and xhr all are undefined even though second API call 'B' is working and getting proper result.

jQuery.Deferred exception: Cannot read property 'status' of undefined TypeError: Cannot read property 'status' of undefined
    at http://localhost:5000/chat.js:95:10
    at j (https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js:2:29999)
    at k (https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js:2:30313) undefined

Can any one please help me to resolve below questions.

  1. I was wondering if this is the correct way of doing promise chain? Because runMethodGeneric function returns promise. But not sure how to use those promises returned by API calls B and C as I am calling those API calls based on the result.
  2. If above is not correct way, how to do the promise chain satisfying requirements (run API-1. If it succeeds and the result of the API response is 'true', run API-2, If it succeeds and the result of API response is 'true', run API-3)
  3. Do I need to check xhr.status === 200 in 'then' block? I think control will reach 'then' block only when API call got succeeded. Is this assumption correct?

Solution

  • You could maybe simplify this with async/await syntax and for...of loop that will allow you to execute request one after the other and you can also add the condition to break out of the loop.

    function fetchData(method) {
      let url = `https://jsonplaceholder.typicode.com/todos/${method}`;
      return $.ajax(url, {
        type: 'GET'
      });
    }
    
    async function runMethods() {
      const methods = [1, 2, 'foo', 3, 4];
    
      for (let method of methods) {
        try {
          const response = await fetchData(method);
    
          // do your checking here
          // break out of the loop if condition true
          if (response.id == 3) {
            console.log(response)
            console.log('exiting on 3')
            break;
          } else {
            console.log(response)
          }
        } catch (err) {
          // you can also break on error here
          console.log(`${err.status} for ${method} method`)
        }
      }
    }
    
    runMethods()
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>