0

I am making several asynchronous ajax calls which must be executed in a specific order and which must pass information to each other. Here is a MWE of my current approach. Even with three API calls it is a bit of a nightmare. With 5 it's impossible to line up the error workflow or to move functions around (also I run out of screen space). Is there a better approach to achieve this same outcome?

/*
 * API Call to get user
 */
$.ajax({
    type: 'POST',
    url: `robin.hood/get_user`,
    data: JSON.stringify({"name":"Joe Dirt"}),
    headers: {Authorization: 'Bearer ' + token},
    datatype: 'json',
    contentType: 'application/json; charset=utf-8',
    success: function (data, text_status, jq_xhr) {
        /*
         * Assume one user is returned only
         */
        let user_id = data;

        /*
         * API Call to get the bank balance of the user
         */
        $.ajax({
            type: 'POST',
            url: `robin.hood/get_user_balance`,
            data: JSON.stringify({"user_id":user_id}),
            headers: {Authorization: 'Bearer ' + token},
            datatype: 'json',
            contentType: 'application/json; charset=utf-8',
            success: function (data, text_status, jq_xhr) {
                /*
                 * We record the balance
                 */
                let balance = data;

                /*
                 * We invest in Gamestop stock
                 */
                $.ajax({
                    type: 'POST',
                    url: `robin.hood/buy_gamestop_stock`,
                    data: JSON.stringify({"user_id":user_id, "amount":balance}),
                    headers: {Authorization: 'Bearer ' + token},
                    datatype: 'json',
                    contentType: 'application/json; charset=utf-8',
                    success: function (data, text_status, jq_xhr) {
                        /* STONKS!!! */
                        });
                    },
                    error: function (jq_xhr, text_status, error_thrown) {
                        /* NO STONKS */
                    }
                });
            },
            error: function (jq_xhr, text_status, error_thrown) {
                /* NO STONKS */
            }
        });
    },
    error: function (jq_xhr, text_status, error_thrown) {
        /* NO STONKS */
    }
});

Related but not so clear questions:

  1. Chaining multiple jQuery ajax requests
  2. jquery how to use multiple ajax calls one after the end of the other
puk
  • 16,318
  • 29
  • 119
  • 199

1 Answers1

1

$.ajax returns a Thenable, which means you can await it inside an async function, which is easier to manage than nested callbacks:

async function run() {
  try {
    const user = await $.ajax({
      type: 'POST',
      url: `robin.hood/get_user`,
      data: JSON.stringify({
        "name": "Joe Dirt"
      }),
      headers: {
        Authorization: 'Bearer ' + token
      },
      datatype: 'json',
      contentType: 'application/json; charset=utf-8',
    })

    const balance = await $.ajax({
      // ...
    })

    const data = await $.ajax({
      // ...
    })

    /* STONKS!!! */
  } catch (e) {
    /* NO STONKS */
  }
}
run()
tklg
  • 2,572
  • 2
  • 19
  • 24
  • I get that what follows the `const user = ...` portion is basically replacing `sucess: ...` The problem I have with this is that if I have, for example, 2 API calls, and both can throw a, for example, ID_NOT_FOUND error, how do I handle that with a `try...catch`? Can I remove the try and use the ajax `success:...error`? – puk Mar 04 '21 at 03:07
  • 1
    I don't know what happens if you mix async and callback together but its probably not the best idea, its better to stick with just one. I'd put each api call in its own async function (`getUser`, `getBalance`, etc) each with its own try/catch for error handling. Then you could just `const user = await getUser(); const balance = await getBalance(user);`. – tklg Mar 05 '21 at 11:44