Local variable becomes undefined in callback function in javascript - javascript

Im a java programmer trying to write javascript cant seem to grasp how scope changes when callbacks are called.
bot.sendmessage below failes to run. Error log says "undefined.bot.sendMessage(formId, resp)"
"use strict";
function Handlers() {
this.bot = undefined;
this.registerHandler = (bot)=>{
this.bot = bot;
bot.on('message', this._messageCallback);
bot.on('inline_query', this._inlineCallback)
}
}
Handlers.prototype = {
_messageCallback: (msg) => {
console.log("New Outline Request from: chat=" + msg.chat.id + ", uid=" + msg.from.id);
var fromId = msg.from.id;
var resp = "Hello there";
this.bot.sendMessage(fromId, resp);
},
_inlineCallback: (msg) => {
console.log("New Inline Request from: uid=" + msg.from.id);
/*
TODO::
check if user is in data base if not log new entry;
*/
}
};
module.exports = Handlers;

First I need to say Teemu is correct. This is an issue with Arrow Functions which I myself am unfamiliar with. If you would like to see an alternative way of acomplishing the same thing without using Arrow Functions take a look at the snippet below.
This code I would change later to be an Immediately-Invoked Function Expression (IIFE) but that is my personal programming habits. I don't know your exact use case here.
"use strict";
/**
* I'm assuming you have this elsewhere?
* If not I have added it to show how to do it
*/
function bot(){
/* ... */
}
bot.prototype = {
sendMessage: function(formId,resp){
console.log("Form: "+formId+" | Message: "+resp);
}
};
/**
* End of my addition
*/
function Handlers() {
this.bot = new bot();
/* ... */
}
Handlers.prototype = {
_messageCallback: function(msg){
/* ... */
var fromId = "fakeid123";
var resp = msg;
this.bot.sendMessage(fromId, resp);
},
_inlineCallback: function(msg){
/* ... */
}
};
var myModule= new Handlers();
myModule._messageCallback("Here is my test msg.");

Related

How to fix " Uncaught Reference Error: autobahn is not defined at HelloworldProxy.connect " error?

I am trying to implement franca IDL using js and autobahn on clientside and wamp c++ server.I am completely newbee to this .js this is the first time I am working on this but I have worked on franca with D-bus so I have idea on franca. Any help and suggestions will help ma a lot.
In clientside i wrote a simple helloworld code
package example.hello
interface HelloWorld {
version {major 1 minor 0}
method sayHello {
in {
String name
}
out {
String message
}
}
}
and generated the autobahn js binding code. Now am taking up the code as below but its showing the below error:
" Uncaught ReferenceError: autobahn is not defined at HelloworldProxy.connect "
hello.html code:
<form>
<br/><br/><br/>
<label>Result: <output id="message" /></label><br/>
<br/><hr/><br/><br/>
<label>Status: <output id="connectionStatus"></output></label>
</form>
<p>This example uses WAMP communication to interact with a C++
server using CommonAPI.</p>
<br/><br/><br/><hr/>
<form>
<br/><br/><br/>
<label>Result: <output id="message" /></label><br/>
<br/><hr/><br/><br/>
<label>Status: <output id="connectionStatus"></output></label>
</form>
<script src="js/HelloworldProxy.js"></script>
<!--script src="js/HelloworldClientBlueprint.js"></script>-->
<script type="text/javascript">
console.log("I am alive!");
var proxy = new HelloworldProxy();
proxy.connect('ws://localhost:8081');
//var clientId = 66;
//var addr =
'local:example.hello.helloworld:v0_1:example.hello.helloworld';
proxy.onOpened = function() {
// your code goes here
connection.onopen = function(session, details) {
console.log("Connected", details);
setStatus("Connected to network.");
};
/**
* Async callback in response to a 'sayHello' call.
*
* #param cid the call id
* #param message
*/
proxy.replySayHello = function(cid, message) {
// your code goes here
};
/**
* API function provided by the proxy for calling method 'sayHello'.
* #param name
*/
proxy.sayHello(name);
};
proxy.onClosed = function(event) {
// your code goes here
connection.onclose = function(reason, details) {
console.log("Connection closed", reason, details);
setStatus("Disconnected.");
}
};
setStatus("Connecting to server...");
connection.open();
function setStatus(text) {
document.getElementById("connectionStatus").value = text;
}
</script>
</body>
</html>
generated autobahn binding code:
function HelloworldProxy() {
this.connection = null;
this.session = null;
this.address =
"local:example.hello.helloworld:v0_1:example.hello.helloworld"
this.callID = 0;
}
HelloworldProxy.prototype.getNextCallID = function() {
this.callID = this.callID + 1;
return this.callID;
};
// call this method to invoke sayHello on the server side
HelloworldProxy.prototype.sayHello = function(name) {
var cid = this.getNextCallID();
var _this = this;
this.session.call(this.address + '.sayHello', [cid, name]).then(
function (res) {
if (typeof(_this.replySayHello) === "function") {
_this.replySayHello(cid, res);
}
},
function (err) {
console.log("Call failed, error message: ", err);
_this.replyError();
}
);
return cid;
};
HelloworldProxy.prototype.connect = function(address) {
var _this = this;
_this.connection = new autobahn.Connection({
url: address,
realm: 'realm1'}
);
_this.connection.onopen = function(session, details) {
console.log("Connected", details);
if (typeof(_this.onOpened) === "function") {
_this.onOpened();
}
_this.session = session;
// subscribing to all broadcasts
}
_this.connection.onclose = function(reason, details) {
console.log("Connection closed", reason, details);
if (typeof(_this.onClosed) === "function") {
_this.onClosed(reason);
}
}
setStatus("Connecting to server...");
_this.connection.open();
};
I need to connect the client with the server and get a response message from the server. The server is working good I have tested it with the help of RESTClint.sh.
hi it worked I just added the display functions in js and thus got output.
similar to below code:
document.getElementById("i1").onclick = function(){
console.log("sending " + Indicator.R_ind);
proxy.Myindicator(Indicator.name);
proxy.replySayHello = function(cid, message) {
document.getElementById("message").value = message;
document.getElementById("d1").innerHTML = message;
};
I worked around and got the solution for above question. I was actually missing autobahn.min.js file (header file) from the autobahn. the connection has been achieved.It took half a day to reach this stage but it was a good experience.
Now the issue is I am not getting how to call the method sayhello in javascript to get the respose from the server.
i.e. : in javascript part I have
/**
* Async callback in response to a 'sayHello' call.
*
* #param cid the call id
* #param message
*/
proxy.replySayHello = function(cid, message) {
// your code goes here
};
/**
* API function provided by the proxy for calling method 'sayHello'.
* #param name
*/
proxy.sayHello(name);
I am not getting how to call these functions any suggestions will help me a lot. Thanks in advance.

Node.Js doesn't execute anonymous functions?? -aws lambda -alexa skill

I'm currently working on a Alexa Skill for my Smart Home.
I created a Lambda function and want to make a http request to a server. but it wont execute any of my anon. functions.
A lambda code example:
/* This code has been generated from your interaction model by skillinator.io
/* eslint-disable func-names */
/* eslint quote-props: ["error", "consistent"]*/
// There are three sections, Text Strings, Skill Code, and Helper Function(s).
// You can copy and paste the contents as the code for a new Lambda function, using the alexa-skill-kit-sdk-factskill template.
// This code includes helper functions for compatibility with versions of the SDK prior to 1.0.9, which includes the dialog directives.
// 1. Text strings =====================================================================================================
// Modify these strings and messages to change the behavior of your Lambda function
const request = require("request");
let speechOutput;
let reprompt;
let welcomeOutput = "Hallo xyz!";
let welcomeReprompt = "xy";
// 2. Skill Code =======================================================================================================
"use strict";
const Alexa = require('alexa-sdk');
const APP_ID = "my id"; // TODO replace with your app ID (OPTIONAL).
speechOutput = '';
const handlers = {
'LaunchRequest': function () {
this.emit(':ask', welcomeOutput, welcomeReprompt);
},
'AMAZON.HelpIntent': function () {
speechOutput = 'Placeholder response for AMAZON.HelpIntent.';
reprompt = '';
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
speechOutput = 'Placeholder response for AMAZON.CancelIntent';
this.emit(':tell', speechOutput);
},
'AMAZON.StopIntent': function () {
speechOutput = 'Placeholder response for AMAZON.StopIntent.';
this.emit(':tell', speechOutput);
},
'SessionEndedRequest': function () {
speechOutput = '';
//this.emit(':saveState', true);//uncomment to save attributes to db on session end
this.emit(':tell', speechOutput);
},
'LichtIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let zimmerSlotRaw = this.event.request.intent.slots.zimmer.value;
console.log(zimmerSlotRaw);
let zimmerSlot = resolveCanonical(this.event.request.intent.slots.zimmer);
console.log(zimmerSlot);
let was_lichtSlotRaw = this.event.request.intent.slots.was_licht.value;
console.log(was_lichtSlotRaw);
let was_lichtSlot = resolveCanonical(this.event.request.intent.slots.was_licht);
console.log(was_lichtSlot);
//THIS IS THE PART WHERE I NEED HELP!!
MakeRequest(function(data){
console.log("asddd");
speechOutput = "This is a place holder response for the intent named LichtIntent, which includes dialogs. This intent has 2 slots, which are zimmer, and was_licht. Anything else?";
var speechOutput = data;
this.emit(':ask', speechOutput, speechOutput);
});
console.log("asdww");
//DOWN TO HERE!!
},
'StromIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let geraet_stromSlotRaw = this.event.request.intent.slots.geraet_strom.value;
console.log(geraet_stromSlotRaw);
let geraet_stromSlot = resolveCanonical(this.event.request.intent.slots.geraet_strom);
console.log(geraet_stromSlot);
let wasSlotRaw = this.event.request.intent.slots.was.value;
console.log(wasSlotRaw);
let wasSlot = resolveCanonical(this.event.request.intent.slots.was);
console.log(wasSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named StromIntent, which includes dialogs. This intent has 2 slots, which are geraet_strom, and was. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'FrageIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let geraetSlotRaw = this.event.request.intent.slots.geraet.value;
console.log(geraetSlotRaw);
let geraetSlot = resolveCanonical(this.event.request.intent.slots.geraet);
console.log(geraetSlot);
let was_frageSlotRaw = this.event.request.intent.slots.was_frage.value;
console.log(was_frageSlotRaw);
let was_frageSlot = resolveCanonical(this.event.request.intent.slots.was_frage);
console.log(was_frageSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named FrageIntent, which includes dialogs. This intent has 2 slots, which are geraet, and was_frage. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'TuerIntent': function () {
//delegate to Alexa to collect all the required slot values
let filledSlots = delegateSlotCollection.call(this);
speechOutput = '';
//any intent slot variables are listed here for convenience
let zeitSlotRaw = this.event.request.intent.slots.zeit.value;
console.log(zeitSlotRaw);
let zeitSlot = resolveCanonical(this.event.request.intent.slots.zeit);
console.log(zeitSlot);
//Your custom intent handling goes here
speechOutput = "This is a place holder response for the intent named TuerIntent, which includes dialogs. This intent has one slot, which is zeit. Anything else?";
this.emit(':ask', speechOutput, speechOutput);
},
'Unhandled': function () {
speechOutput = "The skill didn't quite understand what you wanted. Do you want to try something else?";
this.emit(':ask', speechOutput, speechOutput);
}
};
exports.handler = (event, context) => {
const alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
// To enable string internationalization (i18n) features, set a resources object.
//alexa.resources = languageStrings;
alexa.registerHandlers(handlers);
//alexa.dynamoDBTableName = 'DYNAMODB_TABLE_NAME'; //uncomment this line to save attributes to DB
alexa.execute();
};
// END of Intent Handlers {} ========================================================================================
// 3. Helper Function =================================================================================================
//THESE ARE MY HELPER FUNCTIONS
function url(){
console.log("asd");
return " my server ip";
}
function MakeRequest(callback){
console.log("hallo!");
request.get(url(), function(error, response, body){
console.log("****************************************");
console.log(response);
console.log("****************************************");
console.log(error);
console.log("****************************************");
console.log(body);
console.log("****************************************");
callback("erfolg!");
});
console.log("hffggh");
}
//DOWN TO HERE!!
function resolveCanonical(slot){
//this function looks at the entity resolution part of request and returns the slot value if a synonyms is provided
let canonical;
try{
canonical = slot.resolutions.resolutionsPerAuthority[0].values[0].value.name;
}catch(err){
console.log(err.message);
canonical = slot.value;
};
return canonical;
};
function delegateSlotCollection(){
console.log("in delegateSlotCollection");
console.log("current dialogState: "+this.event.request.dialogState);
if (this.event.request.dialogState === "STARTED") {
console.log("in Beginning");
let updatedIntent= null;
// updatedIntent=this.event.request.intent;
//optionally pre-fill slots: update the intent object with slot values for which
//you have defaults, then return Dialog.Delegate with this updated intent
// in the updatedIntent property
//this.emit(":delegate", updatedIntent); //uncomment this is using ASK SDK 1.0.9 or newer
//this code is necessary if using ASK SDK versions prior to 1.0.9
if(this.isOverridden()) {
return;
}
this.handler.response = buildSpeechletResponse({
sessionAttributes: this.attributes,
directives: getDialogDirectives('Dialog.Delegate', updatedIntent, null),
shouldEndSession: false
});
this.emit(':responseReady', updatedIntent);
} else if (this.event.request.dialogState !== "COMPLETED") {
console.log("in not completed");
// return a Dialog.Delegate directive with no updatedIntent property.
//this.emit(":delegate"); //uncomment this is using ASK SDK 1.0.9 or newer
//this code necessary is using ASK SDK versions prior to 1.0.9
if(this.isOverridden()) {
return;
}
this.handler.response = buildSpeechletResponse({
sessionAttributes: this.attributes,
directives: getDialogDirectives('Dialog.Delegate', null, null),
shouldEndSession: false
});
this.emit(':responseReady');
} else {
console.log("in completed");
console.log("returning: "+ JSON.stringify(this.event.request.intent));
// Dialog is now complete and all required slots should be filled,
// so call your normal intent handler.
return this.event.request.intent;
}
}
function randomPhrase(array) {
// the argument is an array [] of words or phrases
let i = 0;
i = Math.floor(Math.random() * array.length);
return(array[i]);
}
function isSlotValid(request, slotName){
let slot = request.intent.slots[slotName];
//console.log("request = "+JSON.stringify(request)); //uncomment if you want to see the request
let slotValue;
//if we have a slot, get the text and store it into speechOutput
if (slot && slot.value) {
//we have a value in the slot
slotValue = slot.value.toLowerCase();
return slotValue;
} else {
//we didn't get a value in the slot.
return false;
}
}
//These functions are here to allow dialog directives to work with SDK versions prior to 1.0.9
//will be removed once Lambda templates are updated with the latest SDK
function createSpeechObject(optionsParam) {
if (optionsParam && optionsParam.type === 'SSML') {
return {
type: optionsParam.type,
ssml: optionsParam['speech']
};
} else {
return {
type: optionsParam.type || 'PlainText',
text: optionsParam['speech'] || optionsParam
};
}
}
function buildSpeechletResponse(options) {
let alexaResponse = {
shouldEndSession: options.shouldEndSession
};
if (options.output) {
alexaResponse.outputSpeech = createSpeechObject(options.output);
}
if (options.reprompt) {
alexaResponse.reprompt = {
outputSpeech: createSpeechObject(options.reprompt)
};
}
if (options.directives) {
alexaResponse.directives = options.directives;
}
if (options.cardTitle && options.cardContent) {
alexaResponse.card = {
type: 'Simple',
title: options.cardTitle,
content: options.cardContent
};
if(options.cardImage && (options.cardImage.smallImageUrl || options.cardImage.largeImageUrl)) {
alexaResponse.card.type = 'Standard';
alexaResponse.card['image'] = {};
delete alexaResponse.card.content;
alexaResponse.card.text = options.cardContent;
if(options.cardImage.smallImageUrl) {
alexaResponse.card.image['smallImageUrl'] = options.cardImage.smallImageUrl;
}
if(options.cardImage.largeImageUrl) {
alexaResponse.card.image['largeImageUrl'] = options.cardImage.largeImageUrl;
}
}
} else if (options.cardType === 'LinkAccount') {
alexaResponse.card = {
type: 'LinkAccount'
};
} else if (options.cardType === 'AskForPermissionsConsent') {
alexaResponse.card = {
type: 'AskForPermissionsConsent',
permissions: options.permissions
};
}
let returnResult = {
version: '1.0',
response: alexaResponse
};
if (options.sessionAttributes) {
returnResult.sessionAttributes = options.sessionAttributes;
}
return returnResult;
}
function getDialogDirectives(dialogType, updatedIntent, slotName) {
let directive = {
type: dialogType
};
if (dialogType === 'Dialog.ElicitSlot') {
directive.slotToElicit = slotName;
} else if (dialogType === 'Dialog.ConfirmSlot') {
directive.slotToConfirm = slotName;
}
if (updatedIntent) {
directive.updatedIntent = updatedIntent;
}
return [directive];
}
I use the "request" module for my http-request, I think you all know this module.
When I test my function, it gives me NO runtime error!
but the anonymous functions from the MakeRequest call and the request.get call wont execute, and I don't know why.
For Example the console output:
Hallo!,
Asd (very funny.. it gets the params for the request.get.. the bug has to be between the second param(the anon function itself?) in the call and the start of the anon function),
hffggh,
asdww
-the console.logs in the anon. functions doesn't show.
I maybe undestand why the MakeRequest funct. doesn't run -> because the callback from it never came. But why does the request.get not work?? I pasted the necessary parts (the MakeRequest and the helper functions) in a normal node projekt, and it worked!!? -facepalm.... im nearly crying..
My Goal: I want to receive a response from the server.. - thats all. But it just wont go into the function where I can access the response object(s).
(Scroll down to the helper functions)
Please help me out guys, I could really hit my head against the wall.
Reguards

JavaScript doesn't throw error

I am confused about JS behavior, actualy develop large app in CoffeScript, Este-library, Google-closure and React. For sure I can share more info or code, if no idea comes.
This "non-throwing" behavior start, when component (goog.ui.Component) can't by decorate, call not exist func in React or if I simple remove Google Analytic init code -> variable window['ga'] not exist but window['ga'].someFunc() not throw any error. Here is not 1:1 code.
Component = function() { }
Component.prototype.match_ = null;
Component.prototype.show = function() {
'use strict';
console.log(this.match_);
this.match_.functionDoesntExist();
}
Process code like this:
var component = new Component();
component.show();
make output like this:
null
If I replace "Component.prototype.show":
// ...
Component.prototype.show = function() {
'use strict';
try {
console.log(this.match_);
this.match_.functionDoesntExist();
} catch (error) {
console.log("Error detected!", error);
}
}
It will trigger error and show correctly:
"Error detected! TypeError: Cannot read property 'functionDoesntExist' of null(…)"
Here is Google Analytic example, code is 1:1.
goog.provide('core.Analytics');
goog.require('goog.Uri');
/**
#constructor
*/
core.Analytics = function() {
this.ga_ = window['ga'];
return;
}
goog.addSingletonGetter(core.Analytics);
/**
#private
*/
core.Analytics.prototype.ga_ = null;
/**
#public
*/
core.Analytics.prototype.sendPageView = function() {
var page;
page = this.getCurrentPage_();
this.ga_('send', {
'page': page
});
};
/**
#private
#return {string}
*/
core.Analytics.prototype.getCurrentPage_ = function() {
var page, uri;
uri = new goog.Uri(window['location']['href']);
page = uri.getPath();
if (uri.hasQuery()) {
page += '?' + uri.getQuery();
}
if (uri.hasFragment()) {
page += '#' + uri.getFragment();
}
return page;
};
and in some other file:
goog.require('core.Analytics');
core.Analytics.getInstance().sendPageView();
PS: sorry for bad en (:

Getting Compile error in Microsoft JScript (expected)

I tested a code with my friend and the code worked and now I wanted to test this again and got a Compile error in Microsoft JScript
Everything worked before
var iTest = 0;
if (iTest) {
let sText = "This is a template string which can contain variables like ${iTest}";
console.log(sText);
} else if (!iTest) {
let fnc = (iRadius, iPi = 3.14) => {
console.log("The area of the circle with the radius ${iRadius}cm is ${Math.round(iPi * iRadius * iRadius)}cm²");
}
fnc(3.14);
} else {
/* This is never going to be called since else if is already handling the only option besides the if */
}
var fnc = (iAlpha, iBravo, cb) => {
cb(iAlpha + iBravo);
}
fnc(84,255,(iResult) => {
console.log(iResult);
});
Template literals and arrow functions are not available in JScript. The latest version of JScript is based on ES5, and those two features are only available in ES2015. And console is not available in JScript if you are using the Windows Script Host; instead, use WScript.Echo().
var iTest = 0;
if (iTest) {
var sText = "This is a template string which can contain variables like " + iTest;
WScript.Echo(sText);
} else {
var fnc = function(iRadius, iPi) {
iPi = 3.14;
WScript.Echo("The area of the circle with the radius " + iRadius + "cm is " + Math.round(iPi * iRadius * iRadius) + "cm²");
}
fnc(3.14);
}
var fnc = function(iAlpha, iBravo, cb) {
cb(iAlpha + iBravo);
}
fnc(84, 255, function(iResult) {
WScript.Echo(iResult);
});
It would also be nice if you could provide more information about the particular error you are getting. This should fix it, but it would make it easier for us to help if we know exactly what the problem is.

Start object from setInterval?

I have the following reconnect method for Sockjs which almost is fully working:
(function() {
// Initialize the socket & handlers
var connectToServer = function() {
var warbleSocket = new SockJS('http://url.com:5555/warble');
warbleSocket.onopen = function() {
clearInterval(connectRetry);
$('.connect-status')
.removeClass('disconnected')
.addClass('connected')
.text('Connected');
};
warbleSocket.onmessage = function(e) {
$('#warble-msg').text(e.data);
};
warbleSocket.onclose = function() {
clearInterval(connectRetry);
connectRetry = setInterval(connectToServer, 1000);
$('.connect-status')
.removeClass('connected')
.addClass('disconnected')
.text('Disconnected');
};
// Connect the text field to the socket
$('.msg-sender').off('input').on('input', function() {
warbleSocket.send($('.msg-sender input').val());
});
function send(a) {
warbleSocket.send(a);
}
return {
send: send
};
}();
var connectRetry = setInterval(connectToServer, 1000);
})();
The error i am getting is when its trying to reconnect.
Error is:
SyntaxError: missing ] after element list
at this line:
connectRetry = setInterval(connectToServer, 1000);
Any ideas what im doing wrong here?
Your connectToServer variable is not a function, it's an object with a property send that is a function, so it doesn't make sense to say setInterval(connectToServer, 1000). Try this instead:
setInterval(connectToServer.send, 1000);
Why don't you simplify things a bit?
I would put connection stuff inside a specific function and call it from setInterval().
Something like this (use with care since I'm not testing this code, ok?):
(function() {
// Initialize the socket & handlers
var connectToServer = function() {
var warbleSocket;
function connect() {
warbleSocket = new SockJS('http://url.com:5555/warble');
warbleSocket.onopen = function() {
// ...
};
warbleSocket.onmessage = function(e) {
// ...
};
warbleSocket.onclose = function() {
// ...
}
// Connect the text field to the socket
$('.msg-sender').off('input').on('input', function() {
warbleSocket.send($('.msg-sender input').val());
});
function send(a) {
warbleSocket.send(a);
}
return {
send: send
};
}();
// you probably will need to call the first connection
connectToServer();
// and than set connection retry
var connectRetry = setInterval(connectToServer.connect, 1000);
})();
I hope it helps you.
Regards,
Heleno

Categories

Resources