我是 Javascript 新手,一直在阅读 David's Flanagan Guide 以了解总体概况。
这段代码让我很困惑。我无法意识到循环中的 Promise 在“入队”之前是如何“出队”的?
首先我们将所有 Promise 放入 AsyncQueue() 中:
function eventStream(elt, type) {
const q = new AsyncQueue(); // Create a queue
elt.addEventListener(type, (e) => q.enqueue(e)); // Enqueue events
return q;
}
然后我们迭代它的值:
async function handleKeys()
// Get a stream of keypress events and loop once for each one
for await (const event of eventStream(document, "keypress")) {
console.log(event.key);
}
}
所以我想知道“for wait”循环中的“事件”怎么可能在队列中没有事件?我们之前不是已经说过了吗
“Forawait”循环在“Promise”进入“队列”之前将其“出队”。但如何呢? “for wait”运算符不会等到下一个 Promised 得到解决吗?
也许队列 - eventStream(document, "keypress") - 动态变化? 抱歉,我感觉很困惑。
整个代码片段:
/**
* An asynchronously iterable queue class. Add values with enqueue()
* and remove them with dequeue(). dequeue() returns a Promise, which
* means that values can be dequeued before they are enqueued. The
* class implements [Symbol.asyncIterator] and next() so that it can
* be used with the for/await loop (which will not terminate until
* the close() method is called.)
*/
class AsyncQueue {
constructor() {
// Values that have been queued but not dequeued yet are stored here
this.values = [];
// When Promises are dequeued before their corresponding values are
// queued, the resolve methods for those Promises are stored here.
this.resolvers = [];
// Once closed, no more values can be enqueued, and no more unfulfilled
// Promises returned.
this.closed = false;
}
enqueue(value) {
if (this.closed) {
throw new Error("AsyncQueue closed");
}
if (this.resolvers.length > 0) {
// If this value has already been promised, resolve that Promise
const resolve = this.resolvers.shift();
resolve(value);
} else {
// Otherwise, queue it up
this.values.push(value);
}
}
dequeue() {
if (this.values.length > 0) {
// If there is a queued value, return a resolved Promise for it
const value = this.values.shift();
return Promise.resolve(value);
} else if (this.closed) {
// If no queued values and we're closed, return a resolved
// Promise for the "end-of-stream" marker
return Promise.resolve(AsyncQueue.EOS);
} else {
// Otherwise, return an unresolved Promise,
// queuing the resolver function for later use
return new Promise((resolve) => {
this.resolvers.push(resolve);
});
}
}
close() {
// Once the queue is closed, no more values will be enqueued.
// So resolve any pending Promises with the end-of-stream marker
while (this.resolvers.length > 0) {
this.resolvers.shift()(AsyncQueue.EOS);
}
this.closed = true;
}
// Define the method that makes this class asynchronously iterable
[Symbol.asyncIterator]() {
return this;
}
// Define the method that makes this an asynchronous iterator. The
// dequeue() Promise resolves to a value or the EOS sentinel if we're
// closed. Here, we need to return a Promise that resolves to an
// iterator result object.
next() {
return this.dequeue().then((value) =>
value === AsyncQueue.EOS
? { value: undefined, done: true }
: { value: value, done: false }
);
}
}
// A sentinel value returned by dequeue() to mark "end of stream" when closed
AsyncQueue.EOS = Symbol("end-of-stream");
// Push events of the specified type on the specified document element
// onto an AsyncQueue object, and return the queue for use as an event stream
function eventStream(elt, type) {
const q = new AsyncQueue(); // Create a queue
elt.addEventListener(type, (e) => q.enqueue(e)); // Enqueue events
return q;
}
async function handleKeys() {
// Get a stream of keypress events and loop once for each one
for await (const event of eventStream(document, "keypress")) {
console.log(event.key);
}
}
let a = handleKeys();
谢谢有人能解释这个基本问题。 我查遍了整个互联网,但没有找到解释。
Promise 的整个概念(就其名称而言)是,当创建/提供 Promise 时,我们还没有发生解决 Promise 的事件。所以在承诺队列中没有任何事件。这只是对所有事件的抽象,例如将要发生的
keypress
事件。使用 for await
开始迭代未来事件。希望这可以帮助理解。队列并不意味着其中的所有事件都已发生。