我想要做的是創建一個迭代器,它僅在呼叫外部函式時觸發,比如外部事件。
一個簡單地等待自定義事件的迭代器。
function createIteratorWithFunction() {
var thingThatResolves;
var asyncIterable = {
thingThatResolves,
[Symbol.asyncIterator]() {
return {
next() {
return (new Promise((resolve, reject) => asyncIterable.thingThatResolves = (resolve))).then(_ => ({
value: _,
done: false
}));
},
return () {
return {
done: true
}
}
};
}
};
return asyncIterable;
}
iter = createIteratorWithFunction();
(async function() {
for await (let val of iter) {
console.log(val);
}
})()
<button onclick="iter.thingThatResolves('execute');iter.thingThatResolves(3)">execute next!</button>
正如你所看到的,它只決議'execute',而不是3,當然因為promise不能被多次決議,而且它只能異步更新,我理解這一點,但是由于迭代器是異步的,我怎么會創建一個佇列,以便任何可以同步觸發的值也由 檢索next()?
uj5u.com熱心網友回復:
我有一種感覺,有一個涉及承諾鏈的更優雅的解決方案,但它現在正在逃避我。:-) 見行內評論:
function createIteratorWithFunction() {
// Our pending promise, if any
let promise = null;
// The `resolve` function for our `pending` promise
let resolve = null;
// The values in the queue
const values = [];
// The async iterable
const asyncIterable = {
add(value) {
// Add a value to the queue; if there's a pending promise, fulfill it
values.push(value);
const r = resolve;
resolve = pending = null;
r?.();
},
[Symbol.asyncIterator]() {
return {
async next() {
// If we don't have a value...
while (!values.length) {
// ...we need to wait for one; make sure we have something
// to wait for
if (!resolve) {
pending = new Promise(r => { resolve = r; });
}
await pending;
}
// Get the value we waited for and return it
const value = values.shift();
return {
value,
done: false,
};
},
return() {
return {
done: true,
};
}
};
}
};
return asyncIterable;
}
const iter = createIteratorWithFunction();
(async function() {
for await (let val of iter) {
console.log(val);
}
})();
document.getElementById("execute").addEventListener("click", () => {
iter.add("execute");
iter.add(3);
});
<button id="execute">execute next!</button>
這里的關鍵之一是異步迭代可以有重疊的迭代,它不必為此感到困惑。這個實作通過創建它會在需要時同步等待的承諾來避免這種情況。
顯示代碼片段
function createIteratorWithFunction() {
// Our pending promise, if any
let promise = null;
// The `resolve` function for our `pending` promise
let resolve = null;
// The values in the queue
const values = [];
// The async iterable
const asyncIterable = {
add(value) {
// Add a value to the queue; if there's a pending promise, fulfill it
values.push(value);
const r = resolve;
resolve = pending = null;
r?.();
},
[Symbol.asyncIterator]() {
return {
async next() {
// If we don't have a value...
while (!values.length) {
// ...we need to wait for one; make sure we have something
// to wait for
if (!resolve) {
pending = new Promise(r => { resolve = r; });
}
await pending;
}
// Get the value we waited for and return it
const value = values.shift();
return {
value,
done: false,
};
},
return() {
return {
done: true,
};
}
};
}
};
return asyncIterable;
}
const iter = createIteratorWithFunction();
(async function() {
for await (let val of iter) {
console.log("first:", val);
}
})();
(async function() {
for await (let val of iter) {
console.log("second:", val);
}
})();
document.getElementById("execute").addEventListener("click", () => {
iter.add("execute");
iter.add(3);
});
<button id="execute">execute next!</button>
當我必須讓 promise 的resolve函式在 promise executor 函式(你傳遞的函式new Promise)之外訪問時,我永遠不會高興,但正如我所說,帶有 promise 鏈的優雅解決方案正在逃避我。我強烈地感覺到它就在那里……某處…… :-)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/427180.html
標籤:javascript 异步等待 迭代器
