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