5 Awesome JavaScript Promise Tricks

By  on  

The Promise API changed the game in JavaScript. We went from abusing setTimeouts and settling for synchronous operations to doing everything possible to leverage this new async API. Let's check out a handful of awesome Promise API tricks!

Cancel a fetch Request

One problem we instantly complained about with promises was not being able to cancel them. A simple promiseInstance.cancel() would have been excellent but never came. Instead we were given an API that was way more complicated:

const controller = new AbortController();
const { signal } = controller;

fetch("http://localhost:8000", { signal }).then(response => {
    console.log(`Request 1 is complete!`);
}).catch(e => {
    console.warn(`Fetch 1 error: ${e.message}`);
});

// Abort request
controller.abort();

The magic here is providing the signal with each fetch request. In the JavaScript world, we inherit difficult APIs and do wonders to abstract them, and thus we'll find a way to better abstract this API.

waitForTime & waitForever

Waiting for a duration is useful in loads of production and testing situations -- it's never ideal but always helpful. I've used two awesome functions to make my life btter:

/* Wait for milliseconds */
function waitForTime(ms) {
  return new Promise(r => setTimeout(r, ms));
}

/* Usage */
await waitForTime(200);

/* Wait Forever */
function waitForever() {
  return new Promise(r => {});
}

// Usage:
await waitForever();

Don't wait for perfect situations, wait for the time you need.

Async Array Functions

Array functions like forEach, map, and other functions are used frequently without the need for them to be synchronous. We don't think about it there's a fair amount of times we can go async with our operations.

const promises = [1, 2, 3].map(async (num) => {
  console.log(num);
});

await promises;

The difference in caring between async and sync is Promise.allSettled. Go async when you can!

then on Objects

Did you know that you can arbitrarily add a then method on objects to have them treated as a Promise?

j = { then: resolve => fetch("/").then(resolve) }

j.then(res => console.log(res));
// Response {type: "basic", url: "https://davidwalsh.name/", redirected: false, status: 200, ok: true, …}

// ... or an await...
const response = await j;
// Response {type: "basic", url: "https://davidwalsh.name/", redirected: false, status: 200, ok: true, …}

Now you know! An excellent trick most don't know about!

Detect an Async Function

Not something you would need to do often but this post is about tricks, right? If you want to detect an asynchronous function, you always can:

async function myFunction() {

}

const isAsync = myFunction.constructor.name === "AsyncFunction";

JavaScript Promises are something we every day but a broader look at them allows us to innovate! Have any Promise tricks of your own? Please share!

Recent Features

  • By
    Send Text Messages with PHP

    Kids these days, I tell ya.  All they care about is the technology.  The video games.  The bottled water.  Oh, and the texting, always the texting.  Back in my day, all we had was...OK, I had all of these things too.  But I still don't get...

  • By
    An Interview with Eric Meyer

    Your early CSS books were instrumental in pushing my love for front end technologies. What was it about CSS that you fell in love with and drove you to write about it? At first blush, it was the simplicity of it as compared to the table-and-spacer...

Incredible Demos

  • By
    JavaScript Speech Recognition

    Speech recognition software is becoming more and more important; it started (for me) with Siri on iOS, then Amazon's Echo, then my new Apple TV, and so on.  Speech recognition is so useful for not just us tech superstars but for people who either want to work "hands...

  • By
    Create a Dojo Lightbox with dojox.image.Lightbox

    One of the reasons I love the Dojo Toolkit is that it seems to have everything.  No scouring for a plugin from this site and then another plugin from that site to build my application.  Buried within the expansive dojox namespace of Dojo is

Discussion

  1. I love waitForever()! I have coded and used waitForTime for quite some time now (most often with Sindre Sorhus’ delay package on npm) but it never occurred to me to make waitForever!. Definitely useful for testing.

  2. nico

    If you plan to call a function that might be async anyway you could also just test the result for a then method. Because your async function might not be a true modern async function, but maybe just return a promise.

    The waitForTime() is one of my standard async function, but I normally call it sleep(). Another one that helps throttling or waiting for a settled DOM is: await nextFrame(), as in:

    function nextFrame () {
      return new Promise(resolve => requestAnimationFrame(r));
    }
    
  3. I’m either confused about the “Async Array Functions” section, or maybe there is an error?

    const promises = [1, 2, 3].map(async (num) => {/* ... */});
    // promises is an Array
    await promises; // does not await the promises *inside the array
    
    • Yes, I’m under the same impression.

      await [promiseA, promiseB]

      is not the same as

      await Promise.all([promiseA, promiseB])

      — or is it?

  4. Macfly

    Hello David, like answer above : await is only valid **in** async fonction. Why do u use it outside, is there a trick here ?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!