循环播放,直到用JavaScript接收到所有事件为止

时间:2018-10-14 11:10:01

标签: 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个未定义的对象。我一直在寻找解决方案,似乎使用async可能会有所帮助。只是我不了解如何正确使用它

1 个答案:

答案 0 :(得分:0)

要使用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() {
        // ...
    }
}