【发布时间】:2018-11-22 12:35:09
【问题描述】:
我对现代 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");
}
我应该一个接一个地选择还是它们都一样?或者可能取决于环境(节点、浏览器)?
更新,在 cmets 中被问及我想要实现的目标。它是一个简单的可观察对象,当其属性发生变化时会异步触发propertyChanged 事件。这是一个完整的例子,“屈服”部分在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 运行它,预期的输出应该是:
变更前:旧 改动后:新 propertyChanged:数据,旧 -> 新 所有 propertyChanged 处理程序都已被异步调用此输出的顺序很重要,即,我不希望在 data 的 setter 方法返回给调用者之前调用 propertyChanged 的任何事件处理程序。
【问题讨论】:
-
您知道
setImmediate没有标准化吗?你可能想打折那个,因为它本身。 -
@JamesThorpe,不,我不是,感谢您指出。不过,它似乎适用于所有现代浏览器和 Node(IE11 是不可能的)。
-
有趣 - MDN 将其列为mostly not implemented across the board
-
rxjs 是一个反应式 js 库。你可以创建 observables,这对于在 python 中使用生成器会感觉很熟悉。 rxjs-dev.firebaseapp.com
-
@JamesThorpe,你是对的!只有 Edge 和 Node 有
setImmediate。剩下的只有 #1 和 #3。
标签: javascript promise async-await