我有一个等待四个外部事件的函数(我无法控制它们。它们是随机接收的)
function Foo() {
var this.data_1;
var this.data_2;
var this.data_3;
var this.data_4;
}
Foo.prototype.getData = function(){
deviceOne.on('data', (data) => {
this.data_1 = data;
});
deviceTwo.on('data', (data) => {
this.data_2 = data;
});
deviceThree.on('data', (data) => {
this.data_3 = data;
});
deviceFour.on('data', (data) => {
this.data_4 = data;
});
return {
"data_from_device_1": this.data_1,
"data_from_device_2": this.data_2,
"data_from_device_3": this.data_3,
"data_from_device_4": this.data_4
}
};
var foo = new Foo();
console.log(foo.getData()); // {'undefined', 'undefined', 'undefined', 'undefined'}
正如你所看到的,该函数不会等待它们,它将返回 4 个 undefined object 。我一直在寻找解决方案,似乎使用 async有帮助。只是我不明白如何在我的案例中正确使用它
最佳答案
要使用async
(它在这里确实有帮助),首先您需要执行deviceXYZ.on
的 promise 版本:
const waitForData = device => new Promise((resolve, reject) => {
device.on('data', (data) => {
resolve(data);
});
// ...presumably hook up some kind of error event and use `reject` here...
});
然后(我在这里转换为 class
语法,因为如果您使用 async
,则可以使用新的、更简单的表示法):
class Foo {
async getData() {
// ^^^^^
const data = await Promise.all([
// ^^^^^
waitForData(deviceOne),
waitForData(deviceTwo),
waitForData(deviceThree),
waitForData(deviceFour)
]);
this.data_1 = data[0];
this.data_2 = data[1];
this.data_3 = data[2];
this.data_4 = data[3];
return {
data_from_device_1: this.data_1,
data_from_device_2: this.data_2,
data_from_device_3: this.data_3,
data_from_device_4: this.data_4
};
}
}
然后使用它的代码也必须位于 async
函数中:
( async () => {
// ^^^^^
try {
const foo = new Foo();
console.log(await foo.getData()); // {'undefined', 'undefined', 'undefined', 'undefined'}
// ---------^
} catch (e) {
// Handle/report error
}
})();
...或者它可以直接在非async
函数中使用promise:
const foo = new Foo();
foo.getData()
.then(result => {
console.log(result);
})
.catch(error => {
// Handle/report error
});
更多:
<小时/>附注:这是无效语法:
function Foo() {
var this.data_1; // Error here
var this.data_2;
var this.data_3;
var this.data_4;
}
目前,您无需在 JavaScript 中声明属性。然而,不久之后(可能是 ES2019,几乎肯定是 ES2020)class
语法将通过类字段提案进行扩展,目前处于提案流程的第 3 阶段。当发生这种情况时,您可以声明由 Foo
类创建的对象的“形状”(这可能意味着对象经历较少的形状变化,这有助于提高性能;对于阅读代码的人来说,这也是有用的文档)。这会将 Foo
更改为如下所示:
class Foo {
data_1; // These are field (property) declarations
data_2;
data_3;
data_4;
async getData() {
// ...
}
}
关于javascript - 循环直到在 javascript 中接收到所有事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52802022/