Home > Software design >  How do I modify the value of an external scope variable inside a callback in nodejs
How do I modify the value of an external scope variable inside a callback in nodejs

Time:03-07

Good afternoon. I got this Alexa skill class, inside this class I send and receive messages using mqtt. Unfortunately for this library, the mqtt message needs a callback. Here is my code:

export class Launch implements RequestHandler {
    private readonly options = {
        host: 'host',
        port: 8883,
        protocol: 'mqtts',
        username: 'user',
        password: 'password'
    }

    private readonly mqttClient
    private listener: any
    private delayedPromise: any

    // @ts-ignore
    public constructor(private readonly skillHelper: SkillsHelperInterface) {
        this.mqttClient = mqtt.connect(this.options)
        this.mqttClient.on("connect",function() {
            console.log("connect");
        });
    }

    public canHandle(handlerInput: HandlerInput): Promise<boolean> | boolean {
        return this.skillHelper.isType(handlerInput, RequestTypes.Launch.toString())
    }

    public async handle(handlerInput: HandlerInput): Promise<Response> {
        this.waitForMessage(handlerInput, this.mqttClient, this.delayedPromise)

        this.mqttClient.publish("my/test/topic/publisher", "Hello")

        await this.delay(2000)

        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(speechText)
            .getResponse()
    }

    waitForMessage(handlerInput: HandlerInput, mqttClient: MqttClient) {
        this.listener = function(topic: any, message: any) {
            // I want to update this class variable
            this.speechText = message.toString()
        }
        mqttClient.on("message", this.listener);
        mqttClient.subscribe("my/test/topic/subscriber");
    }

    delay(ms: number) {
        return new Promise( resolve => setTimeout(resolve, ms) );
    }
  }

I have this variable called: "this.speechText" which I want to update once the listener is called, but once it exits the listener it doesn't have the value assigned in the listener. I have also tried passing it into the method that contains the listener but it didn't work. Is there anything I can do to update an outer-scope variable inside a callback?

Thanks in advance

CodePudding user response:

This problem happens because you are in a different scope when you are using this.

To solve the problem, you only need to change the listener function to an fat arrow function., like this:

this.listener = (topic: any, message: any) => {
   // I want to update this class variable
   this.speechText = message.toString()
};

Using an arrow function, the this references to a one-up level scope (if exists). Of course, an alternative is using a helper variable to point to the object and not to the function:

const _that = this; // Helper variable
this.listener = function(topic: any, message: any) => {
   // I want to update this class variable
   _that.speechText = message.toString()
};

But I recommend you to use the first option.

If you need more information, check to docs on mdn: Fat Arrow Function

  • Related