我对现代JavaScript(ES8)有些陌生。使用await
,异步地执行代码,即在事件循环的某些未来迭代中继续脚本执行,有哪些首选方式?我看到了以下选项:
async function yield1() {
await Promise.resolve();
console.log("done");
}
async function yield2() {
// setImmediate is non-standard, only Edge and Node have it
await new Promise(done => (setImmediate? setImmediate: setTimeout)(done));
console.log("done");
}
async function yield3() {
await new Promise(done => setTimeout(done));
console.log("done");
}
我应该一个接一个地选择它们还是它们都一样?或者可能取决于环境(节点、浏览器)?
< p >更新,评论中被问到我想要实现什么。这是一个简单的可观察对象,当其属性更改时异步触发
propertyChanged
事件。这里是一个完整的示例,而“yielding”部分在 firePropertyChanged
中:
const EventEmitter = require('events');
class Model extends EventEmitter {
constructor(data) {
super();
this._data = data;
}
get data() {
return this._data;
}
set data(newValue) {
const oldValue = this._data;
if (oldValue !== newValue) {
this._data = newValue;
this.firePropertyChanged('data', newValue, oldValue);
}
}
async firePropertyChanged(property, newValue, oldValue) {
await Promise.resolve().then(() =>
super.emit('propertyChanged', { target: this, property, newValue, oldValue }));
console.log('all propertyChanged handlers have been called asynchronously');
}
}
async function waitForChange(obj) {
await new Promise(resolve =>
obj.once('propertyChanged', args =>
console.log(`propertyChanged: ${args.property}, ${args.oldValue} -> ${args.newValue}`)));
}
async function test() {
const obj = new Model("old");
var change = waitForChange(obj);
console.log(`before change: ${obj.data}`);
obj.data = "new";
console.log(`after change: ${obj.data}`);
await change;
}
test().catch(e => console.error(e));
如果您使用node运行它,期望的输出应该是:
更改前: 旧值 更改后: 新值 属性已更改: data, 旧值 -> 新值 所有propertyChanged处理程序都已异步调用此输出顺序很重要,即我不希望在setter方法返回给调用者之前调用任何
propertyChanged
事件处理程序。
setImmediate
没有标准化?因为这个原因,你可能会想要排除它。 - James Thorpeawait
来完成。 - jfriend00