Is there a way to write async await code that responds to onkeypress events?
Asked Answered
B

3

8

I'd like to write a readKey function that's async, and then await each key being pressed in the browser.

I'd like to build this up into synchronous, normal-looking code that's all based on async-await.

So then I could write a readLine function that does await readKey() until the user hits [enter], and delete the last key if the user hits [back], etc.

And then I could write functions that await readLine(), and write functions that call them, etc.

I just don't know how to bridge the gap between writing a document.onkeypress handler... and putting the keys in that event into some async readKey function that I'd write. In other languages, I could use other multi-threading primitives to get there, but I can't figure out how to in js. I was trying to figure out if there was some way to yield the value, but I can't see how to do that, either.

Bodhisattva answered 25/6, 2017 at 12:58 Comment(2)
Another way to ask is, why can't I "await document.readKey()"?Bodhisattva
How was that rude. I said nothing about anyone but me. Perhaps you should keep your advice to yourselfUppercut
T
13

Yes. Let's break it down:

Is it possible to await a custom thing?

Yes — you can await any Promise. For example, to wait for a timeout:

const timerPromise = new Promise(resolve => setTimeout(resolve, 1000));
await timerPromise;

Is it possible to have a promise for a key press?

Yes — resolve the promise when an event happens.

function readKey() {
    return new Promise(resolve => {
        window.addEventListener('keypress', resolve, {once:true});
    });
}
Thermodynamic answered 25/6, 2017 at 13:9 Comment(1)
The whole application would need to be contained in an async IIFE would it not, if it has any chance of behaving like the OP described? (async function() { ... }()); jsfiddle.net/9yn4nnr6Unwholesome
B
9

Thanks to @Kornel and @Xotic750, here's what I was looking for:

const readKey = () => new Promise(resolve => window.addEventListener('keypress', resolve, { once: true }));

(async function() {
  console.log('Press a key');
  const x = await readKey();
  console.log('Pressed', String.fromCharCode(x.which));

  console.log('Press a key');
  const y = await readKey();
  console.log('Pressed', String.fromCharCode(y.which));
}());
Bodhisattva answered 25/6, 2017 at 13:41 Comment(0)
C
0

This would wait until a keypress event on an element happens

await new Promise(r=>element.addEventListener('keypress', r));

Or a function to wait for any kind of events, can look like this

waitForEvent = (element, type) => new Promise(r=>element.addEventListener(type,r));

Then we can do things like

await waitForEvent(document, "load");
// or 
await waitForEvent(element, "keypress");
Cointreau answered 20/2, 2021 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.