在ES6类中停止setInterval

时间:2017-12-19 20:12:28

标签: javascript node.js ecmascript-6 setinterval

我只想测试多个MQTT客户端在Node v8.9.1应用程序内以不同的时间间隔发送消息。 目前,即使只有一个客户端,此代码也会失败。我无法理解为什么clearInterval在这个课程中不起作用:

const mqtt = require('mqtt');

export default class MQTTClient {
constructor(url, conf, period) {
    this.url = url;
    this.conf = conf;
    this.period = period;
    this.messages = 0;
    this.client = null;
    this.interval = null;
}

getTotalMessages() {
    return this.messages;
}

connect() {
    this.client = mqtt.connect(this.url, this.conf);

    this.client.on('connect', () => {
        this.interval = setInterval(() => {
            this.client.publish(`u${this.conf.clientId}`, 'Hello mqtt');
            this.messages += 1;
            if (this.messages === 3) {
                clearInterval(this.interval);
                console.log(this.interval);
                this.client.end();
            }
        }, this.period);
    });

    this.client.on('error', (error) => {
        console.error(`${this.conf.clientId} error`, error);
    });
}
}

console.log语句实际上打印的内容如下:

Timeout {
    '0': null,
    _called: false,
    _idleTimeout: -1,
    _idlePrev: null,
    _idleNext: null,
    _idleStart: 5580,
    _onTimeout: null,
    _timerArgs: undefined,
    _repeat: null,
    _destroyed: false,
    [Symbol(asyncId)]: 134,
    [Symbol(triggerAsyncId)]: 123 }

为了更完整,我将这个类称为使用Jest进行的单元测试:

test('Multiple MQTT messages', (done) => {
    const mqttURL = `mqtt://localhost:${config.moscaSettings.port}`;
    expect(config.moscaSettings.port).toBe(1883);
    const conf = {
        clientId: concurrencyTokens[0].value,
        username: concurrencyTokens[0].owner,
        password: concurrencyTokens[0].value,
    };

    const mqttClient = new MQTTClient(mqttURL, conf, 1000);
    mqttClient.connect();

    // terminates the test after five seconds
    setTimeout(async () => {
        const res = await Messages.remove({ userName: user }).exec();
        expect(mqttClient.getTotalMessages()).toBe(3);
        expect(res.result.n).toBe(3);
        done();
    }, 5000);
}, 10000);

所以我无法理解为什么它不起作用。使用箭头函数可以保证this指的是类,但间隔不会停止。 有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您正在做的简化版本工作正常。验证对 this.property 的每个引用都是正确的。还要确认您没有登陆OnError。



var c = (function(){
    let interval;
    let count = 0;
    let express = () => {
        interval = setInterval(() => {
	        count++;
            if (count === 3) {
                clearInterval(interval);
            }
            console.log(interval);
        }, 100);
    };
    return {onThing:express};
})();
c.onThing();




答案 1 :(得分:0)

正如@CharlieMartin在评论中指出的那样,我发现connect被多次调用(但这是另一个问题),因此用所有间隔引用填充数组解决了这个问题。我也可以通过记录setInterval对象并在某些打印中看到它有不同的[Symbol(asyncId)]来检测它。 感谢您的支持。

    this.client.on('connect', () => {
        console.log('on connect');
        const interval = setInterval(() => {
            this.client.publish(`u${this.conf.clientId}`, 'Hello mqtt');
            this.messages += 1;
            if (this.messages === 3) {
                this.clearIntervals();
                this.client.end();
            }
        }, this.period);
        this.intervals.push(interval);
    });