0

Nodejs, How do I wait until the previous post request is completed. Below is the Snippet:

var data ="xxxx"
let XMLHttpRequest1 = require("xmlhttprequest").XMLHttpRequest;
var xhr = new XMLHttpRequest1();
xhr.withCredentials = true;
xhr.open("POST", https://corpqa.sts.xxxx.com/adfs/oauth2/token);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
console.log("Execution Order 1");
xhr.addEventListener("readystatechange",  function() {
  if(this.readyState === 4) {
    console.log("Execution Order 2");
    //console.log(this.responseText);

  }
});
console.log("Execution Order 3");

In NodeJS, below is the Output of the above code:

Execution Order 1
Execution Order 3
Execution Order 2

How do I make code to WAIT for response, execute this.readyState ===4. before it proceed to execute console.log("Execution Order 3").

Expected Output

Execution Order 1
Execution Order 2
Execution Order 3
Madhu
  • 3
  • 1
  • Does this answer your question? [How to return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Sebastian Simon Jun 12 '21 at 19:00

3 Answers3

1

Make a promise-ified version of the http request. It can take an optional authToken param.

const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

// return a promise to post data to url
async function post(url, data, authToken) {
  const request = new XMLHttpRequest();
  
  requst.open("POST", url);
  request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  if (authToken) {
    request.withCredentials = true;
    // request.setRequestHeader( ...set an auth header with authToken
  }
  request.send(data);

  return new Promise((resolve, reject) => {
    request.addEventListener("readystatechange", () => {
      console.log("during the request");
      if (request.readyState === 4 && request.status === 200) resolve();
    });
    // todo: error handling
  });
}

Call it like this:

async function orderOfOperationTest() {
  const data ="xxxx"
  const url = "https://corpqa.sts.xxxx.com/adfs/oauth2/token"
  console.log("before the credential request");
  const authToken = await post(url, data); // notice 'await'
  console.log("after the credential request");
  // now pass authToken as the 3rd param to the next call of 'post()'
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • Thanks for your response. Seems like working but I have 2 questions: In the below code it is giving error as it requires 3 parameters and i passed as NULL to make it work. Is there anything else i need to do resolving the error. ``` const authToken = await post(url, data); // notice 'await' ``` After receiving authToken in the above line. Why are we calling below line again. ``` post(url,data,authToken); ``` Also,noticed we are settingup withcredentials=TRUE and sending data again.Why are we doing this? ``` if (authToken) { request.withCredentials = true; } ``` – Madhu Jun 12 '21 at 21:20
  • @Madhu, I might misunderstand your comment, but the post function doesn't require the third parameter. If the authToken is null it assumes a non-authed request. If you pass an auth token it augments the request with it. – danh Jun 12 '21 at 23:21
  • We are getting authToken with below code ``` await post(url, data) ``` authToken is what we get from the response of above function, then why do we call below passing authToken and set "request.withCredentials = true;" what happens whe don't se withCredentials = true ``` post(url,data,authToken) ``` – Madhu Jun 13 '21 at 06:53
0

Use async/await.
For example:

  1. firstTask()
  2. await secondTask()
  3. thirdTask()
    The execution will wait for the 'secondTask' to finish before it executes the third task.

async function doSomething() {
  try{
    firstTask();
    await callAPI(options); // options with POST operations
    thirdTask();
  }catch(error){
    console.log("error occured ", error);
  }
}
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
novice2ninja
  • 333
  • 5
  • 5
  • Thanks for your response. Below are the changes i made and still getting the same output. Any help on this would be great! ![Screenshot of the updated Snippet](https://ibb.co/Sn0rkvm). – Madhu Jun 12 '21 at 19:44
0

Javascript is a synchronous language. It will execute all the lines and store those callbacks functions in the internal queue until it it called.

// the second parameter define the callback function. 
xhr.addEventListener("readystatechange",  function() {
      if(this.readyState === 4) {
        console.log("Execution Order 2");
        //console.log(this.responseText);
    
      }
    });

In order to have a non-blocking waiting of readyState == 4, u will need to put it inside the callback function like this.

xhr.addEventListener("readystatechange",  function() {
      if(this.readyState === 4) {
        console.log("Execution Order 2");
        //console.log(this.responseText);
        console.log("Execution Order 3");
    
      }
    });
j.f.
  • 184
  • 9
  • We need to WAIT until we get response from the API before we move further. Our Scenario is we are getting Authentication Token from API as a response before we move forward with other calls. Authenticaiton Token is required for other functions to execute. – Madhu Jun 12 '21 at 19:30
  • @Madhu so this should tell you that all steps after getting the auth token must be inside the callback (or called from this callback). – Evert Jun 12 '21 at 20:00