function* range() {
yield 1;
yield 2;
yield 3;
}
for (let i of range()) {
console.log(i);
}
async function* async_range() {
yield Promise.resolve(1);
yield Promise.resolve(2);
yield Promise.resolve(3);
}
for await (let i of async_range()) {
console.log(i);
}
Could we adopt this pattern for:
new PerformanceObserver(lst => {
lst.getEntries().forEach(entry => { console.log(entry); });
}).observe({type: "layout-shift", buffered: true});
async function *PO2it(args) {
let resolve;
new PerformanceObserver(l => {
resolve(l.getEntries());
}).observe(args);
for (;;) {
const entries = await new Promise(resolve_ => {
resolve = resolve_;
});
for (let entry of entries) {
yield entry;
}
}
}
for await (let entry of PO2it({type: 'layout-shift', buffered: true})) {
console.log(entry);
}
// From: https://github.com/tc39/proposal-async-iteration/issues/99
function deferred() {
const def = {}
def.promise = new Promise((resolve, reject) => {
def.resolve = resolve
def.reject = reject
})
return def
}
class AsyncQueue {
constructor(initializer) {
// TODO(mmocny): Can probably replace the { type, value } by just storing promises in queue
this.queue = []
this.waiting = []
initializer({
next: value => {
if (this.waiting.length > 0) {
const consumer = this.waiting.shift()
consumer.resolve({
done: false,
value
});
return;
}
this.queue.push(Promise.resolve({
done: false,
value
}));
},
throw: error => {
if (this.waiting.length > 0) {
const consumer = this.waiting.shift()
consumer.reject(error)
return;
}
this.queue.push(Promise.reject(item.value));
},
return: value => {
if (this.waiting.length > 0) {
const consumer = this.waiting.shift()
consumer.resolve({
done: true,
value
});
return;
}
this.queue.push(Promise.resolve({
done: true,
value
}));
}
})
}
next() {
if (this.queue.length > 0) {
// If there are items available then simply put them
// into the queue
const item = this.queue.shift()
if (item.type === 'error') {
return Promise.reject(item.value)
} else {
return Promise.resolve({
done: item.type === 'return',
value: item.value
})
}
} else {
// If there's nothing available then simply
// give back a Promise immediately for when a value eventually
// comes in
const def = deferred()
this.waiting.push(def)
return def.promise
}
}
[Symbol.asyncIterator]() {
return this
}
}
// Usage:
function PO2it(args) {
return new AsyncQueue(produce => {
new PerformanceObserver(lst => {
lst.getEntries().forEach(entry => { produce.next(entry); });
}).observe(args);
});
}
for await (let entry of PO2it({type: 'layout-shift', buffered: true})) {
console.log(entry);
}