Kiren S
Kiren S

Reputation: 3097

Asynchronous Blocking Request in Javascript: Return value from async function

I am using async and await for achieving this. Following is my code and it is working as expected.

function publish() {    
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve("SUCCESS");
    }, 3000);  
  });
}
var res;
async function sendRequest() {
  console.log("START\n");
  res = await publish();
  console.log("RESULT: ",res)
  console.log("END\n");
}
sendRequest();

Following is the output:

START

SUCCESS

END

But what I am trying to achieve is given below:

function publish() {    
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve("SUCCESS");
    }, 3000);    
  });
}
var res;
async function sendRequest() {
  console.log("START\n");
  res = await publish();
  console.log("RESULT: ",res)
  console.log("END\n");
  return res;
}

/**
 * EXPECTED BEHAVIOUR
 * Assume this function is an action of a controller class
 * It will call sendRequest() and waits for its response.
 * Once received, it will return that response to the client who called the action.
 */
function controller () {
  return sendRequest();
}    
/**
 * ACTUAL BEHAVIOUR: It will out put following
 * START
 * FINAL RESPONSE Promise { <pending> } 
 * RESULT:  SUCCESS
 * SEND
 */
var endResult = controller (); 
console.log("FINAL RESPONSE",endResult);

So my question is why this FINAL RESPONSE Promise { <pending> } is printed before RESULT: SUCCESS.

Upvotes: 1

Views: 374

Answers (3)

Estus Flask
Estus Flask

Reputation: 222875

async..await is syntactic sugar for promises that provides syncronous-like flow of control. async function is just a function that always returns a promise. Each async function can be rewritten as regular function that uses Promise explicitly and returns a promise.

I don't want to use then() in my controller.

Then controller can optionally be async, and the function where it is called should be async:

let endResult = await controller();

Otherwise control flow results in this infamous problem.

Is it possible using while loop?

while and other loop statements support async..await. As long as the loop is performed inside async function, it is:

while (condition) {
    let endResult = await controller();
    // ...
}

It's preferable to use async..await for this purpose, because desugared version is less appealing and harder to comprehend:

let resultsPromise = Promise.resolve();

while (condition) {
    resultsPromise = resultsPromise
    .then(() => controller())
    .then(endResult => {
        // ...
    });
}

resultsPromise.then(() => { /* loop has finished */ })

Upvotes: 1

Vladu Ionut
Vladu Ionut

Reputation: 8193

You can add a wrapper function

// Code goes here
(async function(){

function publish() {

  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve("SUCCESS");
    }, 3000);

  });
}

var res;

async function sendRequest() {
  console.log("START\n");
  res = await publish();
  console.log("RESULT: ",res)
  console.log("END\n");
  return res;
}

/**
 * EXPECTED BEHAVIOUR
 * Assume this function is an action of a controller class
 * It will call sendRequest() and waits for its response.
 * Once received, it will return that response to the client who called the action.
 */
function controller () {
  return sendRequest();
}

/**
 * ACTUAL BEHAVIOUR: It will out put following
 * START
 * FINAL RESPONSE Promise { <pending> } 
 * RESULT:  SUCCESS
 * SEND
 */
var endResult = await  controller (); 
console.log("FINAL RESPONSE",endResult);
}())

Upvotes: 0

Csaba
Csaba

Reputation: 419

You have to handle the last async function as a Promise, like:

function controller () {
  return sendRequest()
}

controller().then(endResult => console.log("FINAL RESPONSE",endResult)) 

Upvotes: 0

Related Questions