1

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.

  • If this is the behaviour of async await, how can I achieve my expected behaviour. I don't want to use then() in my controller.
  • Is it possible using while loop? May be I am wrong. It would be great if any one can guide me.
Abhilash Ravindran C K
  • 1,818
  • 2
  • 13
  • 22
Kiren S
  • 3,037
  • 7
  • 41
  • 69

3 Answers3

1

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 */ })
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
0

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

function controller () {
  return sendRequest()
}

controller().then(endResult => console.log("FINAL RESPONSE",endResult)) 
Csaba
  • 421
  • 4
  • 8
  • 1
    The `async` keyword on controller is doing nothing here. – Keith Mar 22 '18 at 10:17
  • Well, makes sense because the `sendRequest` returns a `Promise`. – Csaba Mar 22 '18 at 10:18
  • The await statement is required... The promise will show as resolved before it is actually resolved – Nick Prozee Mar 22 '18 at 10:21
  • 1
    @NickProzee No it won't `sendRequest` is returning a Promise, all the controller here will be doing is returning the `Promise` that sendRequest has already created.. The await will be wrapping a Promise inside a Promise, a pointless thing to do.. – Keith Mar 22 '18 at 10:23
  • 1
    He edited the post, before it had the async in front of it. So in that example the promise would have resolved before actually resolving. Indeed, removing the async statement is a cleaner option – Nick Prozee Mar 22 '18 at 10:25
  • @NickProzee Indeed, I see what you mean now. – Keith Mar 22 '18 at 10:26
0

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);
}())
Vladu Ionut
  • 8,075
  • 1
  • 19
  • 30