javascript - 循环直到在 javascript 中接收到所有事件

标签 javascript node.js

我有一个等待四个外部事件的函数(我无法控制它们。它们是随机接收的)

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/

相关文章:

javascript - 如何提高这个 MongoDB/Mongoose 查询的性能?

node.js - 带有nodejs和express的静态文件夹

javascript - 如果未读取响应,为什么 Node http 客户端会继续运行?

node.js - yarn 尝试安装 node-sass 的问题

两天之间的Javascript天数计算

javascript - 在 AngularJS 指令上需要 :ngModel vs. 范围:{ ngModel: '=' }

javascript - Vue.Js 中的联系表单

javascript - iframe 以外的 javascript 变量名冲突的解决方案?

javascript - 根据对象数组中的数据计算平均值并存储在对象的特定键中

javascript - XML文件和dtd关联