1

I have just started to learn Promises in Javascript, and happened upon async/await.

In my understanding, if I specify a function, to be async, javascript will always wrap the content of my function and return a Promise instead of whatever I am returning.

Let's presume the following scenario:

async function httpRequest() {
   oReq = new XMLHttpRequest();
   oReq.addEventListener("load", function() {
      return this.responseText;
   });

   oReq.open("GET", "http://some.url.here");
   oReq.send();
}

httpRequest().then(function(httpResult) {
    console.log(httpResult);
}); 

Am I correct in assuming, that the above situation will not work, as httpRequest() is not returning anything, the callback of XMLHttpRequest returns something only, thus my result will most likely be undefined?

If yes, how would I be able to fix httpRequest() so it will work in an async/await scenario?

Adam Baranyai
  • 3,635
  • 3
  • 29
  • 68
  • `httpRequest()` doesn't need to be marked `async` because it isn't `await`ing anything. If you return the asynchronous operation, then you can do `await httpRequest()` in a separate `async` function. – Tyler Roper Dec 19 '19 at 19:01
  • it's marked as `async` so that I can `then` it in the next line. I wanted to use the languages functionality, that it wraps my function as a `Promise` automatically, instead of me having to return a `Promise` – Adam Baranyai Dec 19 '19 at 19:02
  • You don't need `async` to use `then()`, you just need to return a promise in one way or another. You can either return the promise, or if you prefer to keep it `async`, return the *awaited* promise (essentially taking a promise, unwrapping it with `await`, and then re-wrapping it). – Tyler Roper Dec 19 '19 at 19:03
  • Possible duplicate: [In JavaScript how do I/should I use async/await with XMLHttpRequest?](https://stackoverflow.com/questions/48969495/in-javascript-how-do-i-should-i-use-async-await-with-xmlhttprequest) – Tyler Roper Dec 19 '19 at 19:05

2 Answers2

4

What you have here is an async function that performs an async operation, where that operation does not use promises. This means that you need to setup a function that manages and returns a promise explicitly. You don't need the async keyword here, since you want to explicitly return a Promise that you create, and not a promise created for you by the async keyword (which you cannot directly manage).

function httpRequest() {

   // Return a promise (this is what an async function does for you)
   return new Promise(resolve => {
     const oReq = new XMLHttpRequest();
     oReq.addEventListener("load", function() {

        // Resolve the promise when the async operation is complete.
        resolve(this.responseText);
     });

     oReq.open("GET", "http://some.url.here");
     oReq.send();
   };
}

Now that the function explicitly returns a promise, it can be awaited just like an async function. Or used with then() like any promise.

async function someFunction() {
  // await
  const awaitedResponse = await httpRequest();
  console.log(awaitedResponse);

  // or promise chain
  httpRequest().then(responseText => console.log(responseText));
};
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • `You can't actually use the async keyword here, since you nee to actually return a Promise.` - well you can still certainly use the async keyword and also return the promise, it would just be redundant – Klaycon Dec 19 '19 at 19:27
  • _Yo dawg, I heard you like promises. So I returned a promise that resolves a promise so you can async while while you async._ That is to say, sure you technically could. But that would not be a good thing to do :) – Alex Wayne Dec 19 '19 at 19:29
  • 1
    Promises auto-unwrap - `.then()` and `await` both automatically follow promise chains so it's practically no difference aside from being redundant – Klaycon Dec 19 '19 at 19:34
-1

Basically, you are trying to write an async function without having anything in that function to await. You use async/await when there is some asynchronous-ness in the code, while in yours, there isn't.

This is an example that might be useful:

const getItemsAsync = async () => {
    const res = await DoSomethingAsync();
    return res.items;
}

const items = await getItemsAsync();

As you can see, DoSomethingAsync is an asynchronous function I await the result for, which is res. At that point, the code will pause. Once the promise will be resolved, the code will resume and therefore will return res.items, which means that items will actually contain the result of the async function.

Also, async/await is just a spacial syntax that makes the code more readable, by giving it a more synchronous form (not substance).

If you really want to make it asynchronous, you can promisify your synchronous code in order to make it return a promise to await, that will then be either resolved or rejected.

Kenna
  • 302
  • 4
  • 15