Question

I have 2 arrays with email address that I want to feed to the function below, one after the other (not in parallel) and then perform a final function.

I've been looking at examples trying to figure out the correct way to chain these, but I think I'm now more confused than when I started. Tried playing with Promise.all to ensure steps completed before going to next but that was a disaster.

eg: (do array 1).then(do array 2).then(final function)

EmailArray.forEach(fGetUserId(X)) and push to IdArray

function fGetUserId(X) {

        $.ajax({ // get the Ids of users, return to populate IdArray
            url: xhost + "/portal/_api/web/SiteUsers?$select=Id&$filter=Email eq '" + X + "'",
            type: "GET", headers: { "Accept": "application/json;odata=verbose", }, //verbose
            success: function (data) {
                var xuserid = data.d.results[0].Id;
                return xuserid;
            },
            error: function (error) { alert(JSON.stringify(error)); }
        });    
    }

Help?

Was it helpful?

Solution

JQuery AJAX does not use native JS promises. You can observe this by the way they defined a success and error callback.

You can explore using fetch https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API, which is a reasonable browser API since you are already using Promise. I'll provide examples for both fetch and ajax:

/**
  @returns {Promise.<number|void>}
*/
async function fGetUserId(x) {
  /** @type {Promise.<any>} */
  let fetchPromise = fetch(xhost + "/portal/_api/web/SiteUsers?$select=Id&$filter=Email eq '" + X + "'", {
      method: "GET",
      headers: {
        Accept: "application/json;odata=verbose"
      }
    }
  ).then(x => x.json()); // convert response to JSON, aka Promise.<Response> to Promise.<any>

  let idPromise = fetchPromise
    .then(data => {
      var xuserid = data.d.results[0].Id;
      return xuserid;
    }) // Promise.<any> to Promise.<number>
    .catch(err => alert(JSON.stringify(err))); // in case of error, it becomes Promise.<void> instead, since we do not return anything within the catch()
  let userid = await idPromise; // Promise.<number|void> to number|void.
  return userid; // number (but actually Promise.<number|void> since fGetUserId has the async modifier in its signature)
}
/**
  @returns {Promise.<number|void>}
*/
async function fGetUserId(x) {
  /** @type {Promise.<number|void>} */
  let myPromise = new Promise((resolve, reject) => {
    $.ajax({
      url: xhost + "/portal/_api/web/SiteUsers?$select=Id&$filter=Email eq '" + X + "'",
      type: "GET",
      headers: { Accept: "application/json;odata=verbose", }, //verbose
      success: function (data) {
        var xuserid = data.d.results[0].Id;
        resolve(xuserid); // signify the promise succeeded with xuserid as return value
      },
      error: function (error) {
        alert(JSON.stringify(error));
        reject(); // signify the promise faulted with no return value
      }
    });
  });
  let userid = await myPromise; // Promise.<number|void> to number|void.
  return userid; // number (but actually Promise.<number|void> since fGetUserId has the async modifier in its signature)
}

There might be slight errors as I didn't test the code, but I hope the gist is still conveyed!

To call this code, you run this:

/** @type {string[]} */
let EmailArr = ["..", "..", ".."];

/** @type{(Promise.<number|void>)[]} */
let promiseArr = EmailArr.map(x => fGetUserId(x)); // map an array of emails to an array of promises

Promise.all(promiseArr) // wait for array of promises to resolve into array of userid, (aka Promise.<number|void>)[] to (number|void)[]
  .then(userids => console.log("done!", userids)
  .catch(err => console.error(err));

Note that Promise.all() itself is a Promise. You can use .then() to handle it as I did, or use await. Note that await can only be used in an async function, so you might want to declare a global anonymous async function:

(async () => {
  // You can use "await" here
})();
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top