When I try to use this in my VueJs methods I get the following error
this is undefined
I think that I shouldn't use arrow functions because their this does not bind to the context I expect it to.
I try with a regular function and get the error above.
What I've tried so far
methods: {
connection(){
new elasticsearch.Client({...});
client.search({...})
.then(function (resp) {
var hits = resp.aggregations;
this.tmp = hits[1].value;
}, function (err) {
console.trace(err.message);
});
}
}
I cannot use the this that I want to in the functions passed to .search and .then . How can I have this bind to my VueJs instance so I can access data, computed, etc...?
You should use arrow function to save this context, and don't forget that inside Vue methods this refers to the current instance.
data() {
return {
counter:0,
connections:2,
tmp: 0,
}
},
methods: {
connection() {
// ...
var client = new elasticsearch.Client({
host: 'xxxxxxxxxxxx'
});
client.search({
[...]
}).then((resp) => {
var hits = resp.aggregations;
this.tmp = hits[1].value;
}, (err) => {
console.trace(err.message);
});
}
}
You can assign this variable to local variable(self) and use it in .then function
data () {
return {
counter:0,
connections:2
}
},
methods: {
connection(){
var self = this;
var tmp=0
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'xxxxxxxxxxxx'
});
client.search({
"index":"400000",
[...]
}
}).then(function (resp) {
var hits = resp.aggregations;
self.tmp=hits[1].value;
}, function (err) {
console.trace(err.message);
});
console.log("tmp:",tmp)
}
}
Related
I'm at the beginning of making a simple one page photo steam app with the public Flickr stream, but with what i've done so far i'm getting the error
'Cannot set property 'data' of undefined'.
My code:
<b-container>
<b-row>
<b-col>
<p md="4" v-for="photo in Photos">{{photo.id}}</p>
</b-col>
</b-row>
</b-container>
</template>
<script>
import jsonp from "jsonp";
export default {
name: 'PhotoFeed',
data: function() {
return {
Photos: [],
apiURL: "https://api.flickr.com/services/feeds/photos_public.gne?format=json"
}
},
mounted(){
this.getFlickrFeed();
},
methods: {
getFlickrFeed(){
let jsonp = require('jsonp');
jsonp(this.apiURL, {name:'jsonFlickrFeed'}, function(err,data) {
this.data = data;
var self = this;
if (err){
console.log(err.message);
}
else {
this.Photos = self.data;
}
});
}
}
}
</script>
You want var self = this to be outside the anonymous function definition so this keyword is not shadowed by the new function;
getFlickrFeed () {
let jsonp = require('jsonp');
var self = this; // now self refers to the vue component and can
// access the Photos property in data
jsonp(this.apiURL, { name:'jsonFlickrFeed' }, function (err,data) {
if (err){
console.log(err.message);
}
else {
// also use self.Photos to refer to the Vue component
self.Photos = data;
}
});
}
The simplest is to use an arrow function instead of an anonymous function:
jsonp(this.apiURL, { name:'jsonFlickrFeed' }, (err, data) => {
if (err) {
console.log(err.message);
}
else {
this.Photos = data;
}
})
You could use arrow function ()=> and use this in the callback context as follows :
jsonp(this.apiURL, {name:'jsonFlickrFeed'}, (err,data)=> {
this.data = data;
if (err){
console.log(err.message);
}
else {
this.Photos = this.data;
}
});
I think this is a syntax error but I'm having trouble finding documentation. I keep getting 'Parsing Error: Unexpected Token {". It says its to do with the 'YesIntent', but won't give specifics. I'm new to JS, but I can't see what could be the problem. Every '{' has a matching '}'.
Any insights would be appreciated. Thank you.
const Alexa = require("alexa-sdk");
const appId = ''; //'';
exports.handler = function(event, context, callback) {
const alexa = Alexa.handler(event, context);
alexa.appId = appId;
alexa.registerHandlers(handlers);
alexa.execute();
};
const handlers = {
'LaunchRequest': function() {
this.emit('YesIntent');
},
'YesIntent': function() {
getData(callback(title) {
this.response.speak('Here are your data ' + title);
this.emit(':responseReady');
}),
};
function getData() {
var ddb = new AWS.DynamoDB.DocumentClient({
region: 'us-west-1'
});
var params = {
TableName: 'WallyFlow_StartTime',
Key: 'TimeStamp',
};
ddb.get(params, function(err, data) {
if (err) {
callback(err, null);
} else {
title = data.Item.title;
}
});
}
Sorry, in this style you need more braces :) Updated to:
'YesIntent': function () {
getData( {
callback(title) {
this.response.speak('Here are your data ' + title);
this.emit(':responseReady');
}})
}};
I suspect it should be something like this. callback should be the name of the parameter to the getData() function, not something you call in the argument. The argument to getData() should be a function.
And getData() should call the callback function in the non-error case as well as the error case.
You also need an extra } to end the handlers object, and the end of the statement that calls getData() should be ;, not ,.
const handlers = {
'LaunchRequest': function() {
this.emit('YesIntent');
},
'YesIntent': function() {
getData(function(title) {
this.response.speak('Here are your data ' + title);
this.emit(':responseReady');
});
}
};
function getData(callback) {
var ddb = new AWS.DynamoDB.DocumentClient({
region: 'us-west-1'
});
var params = {
TableName: 'WallyFlow_StartTime',
Key: 'TimeStamp',
};
ddb.get(params, function(err, data) {
if (err) {
callback(err, null);
} else {
title = data.Item.title;
callback(title);
}
});
}
I'm trying to call a function (refresh_access_token) from another one and create a Promise chain from that. But the return function inside refresh_access_token is not working. The refresh_access_token doesn't return to it's caller when it completes.
I'm receiving this message:
Unhandled rejection TypeError: Cannot read property 'then' of undefined
How can I fix this?
These are the 2 function code:
exports.refresh_access_token = function(environment_hash) {
var MercadoLibre = require('../../models/index').MercadoLibre;
var needle = require('needle');
const load = require('express-load');
var meli = require('mercadolibre');
var request=require('request');
const mysql = require('mysql');
const dotenv = require('dotenv').config({path: '../../.env'});
var oauth_url = 'https://api.mercadolibre.com/oauth/token';
var env_hash = environment_hash;
where = { environment_hash: env_hash };
MercadoLibre.findOne({where: where}).then(function (account) {
if (!account) {
// Item not found
} else {
// Found an item, update it
needle.post(oauth_url, {
grant_type: 'refresh_token',
client_id: process.env.MERCADOLIBRE_CLIENT_ID,
client_secret: process.env.MERCADOLIBRE_SECRET,
refresh_token: account.refresh_token
}, {
}, function (err, res, body) {
if (body) {
expires_in = new Date();
expires_in.setUTCHours(0);
expires_in.setTime(expires_in.getTime() + 21600*1000);
values = {
refresh_token: body.refresh_token,
expires_in: expires_in
};
where = { environment_hash: env_hash };
return MercadoLibre.update(values, {where: where});
}
});
}
});
}
exports.run_mercadolibre_jobs = function() {
var MercadoLibre = require('../../models/index').MercadoLibre;
var values = {
attributes: ['environment_hash'],
raw: true
};
MercadoLibre
.findAll(values)
.then(function(accounts) {
Promise.all(accounts.map(function(account) {
module.exports.refresh_access_token(account.environment_hash)
.then(function(response) {
console.log(response);
})
.catch(function(response){
console.log(response);
});
}));
});
}
Your function refresh_access_token is not returning anything. Your only return statement is inside the needle.post callback. You should be first returning:
return MercadoLibre.findOne(...);
However, you are mixing promises, with callbacks (used in your needle.port call). I would suggest reviewing Promises vs Callbacks and how to use them together. Here is a good thread on how to convert callback-apis to promises: How do I convert an existing callback API to promises?.
Another alternative would be to replace using needle with a promise-supported node library:
Axios
Request Promise
Guys how can I stub params in POST request, for example here a part of function
gridCalculator : function(req,res){
// calculation logic
var options=[];
options.dateFirstLicensed = req.param('DateFirstLicensed');
options.dateFirstInsured = req.param('DateFirstInsured');
options.claimList = req.param('ClaimList');
options.suspenList = req.param('SuspenList');
...etc
if I did this
it('grid Calculate', function (done) {
var req = {
'DateFirstLicensed' : "01-01-2010",
'DateFirstInsured': "01-01-2011",
'ClaimList': ['05-03-2012'],
'SuspenList': [{'StartDate':'05-03-2012','EndDate':'05-05-2012' }]
};
gridCalculator.gridCalculator(req,function (err, result) {
result.should.exist;
done();
});
});
I get error because I'm simply passing an object not POST request
TypeError: req.param is not a function
Two options come to mind (there are probably a lot more):
Option 1: Define the param function yourself:
it('grid Calculate', function (done) {
var params = function(param) {
switch (param) {
case 'DateFirstLicensed':
return "01-01-2010";
case 'DateFirstInsured':
... //do the same for all params
}
};
var req = {
param: params
};
gridCalculator.gridCalculator(req,function (err, result) {
result.should.exist;
done();
});
});
Option 2: Use tools like supertest to create calls to your server's endpoint.
The problem is that you don't stub the function that is used in your gridCalculator method in your test.
It should look like this:
it('grid Calculate', function (done) {
var testParams = {
'DateFirstLicensed' : "01-01-2010",
'DateFirstInsured': "01-01-2011",
'ClaimList': ['05-03-2012'],
'SuspenList': [{'StartDate':'05-03-2012','EndDate':'05-05-2012'}]
};
var req = {
param: function (paramName) {
return testParams[paramName];
}
};
gridCalculator.gridCalculator(req,function (err, result) {
result.should.exist;
done();
});
});
Update
Now the method socket.disconnect(close) has been included in angular-socket-io. It has a Boolean parameter 'close', if true, closes also the underlying connection.
I am using btford/angular-socket-io
What is the correct approach to disconnect the client?
I am trying to implement the following scenario
user login --> connect to socket
user logout --> disconnect from socket
repeat (1) (2)
I succeeded to implement the connect (1) but I am having trouble with the disconnect (2)
This is what I tried: in my Authentication service I have the following
factory('AuthenticationService', function(socketFactory) {
var mySocket;
var service = {
//...
login: function(credentials) {
var login = $http.post('/login', credentials);
return login.then(function(response) {
service.currentUser = response.data.user;
if ( service.isAuthenticated() ) {
// **connect to socket on login**
mySocket = socketFactory({ioSocket: io.connect('http://localhost')});
}
return service.isAuthenticated();
});
},
logout: function(redirectTo) {
var logout = $http.get('/logout');
logout.success(function() {
service.currentUser = null;
mySocket.disconnect(); // **disconnect on logout (not working)**
redirect(redirectTo);
});
return logout;
},
//...
};
return service;
})
mySocket.disconnect();
gives the following error
TypeError: Object # has no method 'disconnect'
mySocket.disconnect() works if instead of
mySocket = socketFactory({ioSocket: io.connect('http://localhost')});
I use
mySocket = io.connect('http://localhost');
your code looks correct. I think the problem is variable hoisting, mySocket is hoisting.
read here
My understanding is that btford/angular-socket-io wraps the socket instance in the socketFactory
but does not expose a disconnet() method
therefore it cannot be used to disconnect the socket from the client side.
The solution is very simple in fact :
Go edit the "socket.js" file from the Btford angular-socket module and you'll see :
var wrappedSocket = {
on: addListener,
addListener: addListener,
emit: function (eventName, data, callback) {
return socket.emit(eventName, data, asyncAngularify(socket, callback));
},
removeListener: function () {
return socket.removeListener.apply(socket, arguments);
},
// when socket.on('someEvent', fn (data) { ... }),
// call scope.$broadcast('someEvent', data)
forward: function (events, scope) {
if (events instanceof Array === false) {
events = [events];
}
if (!scope) {
scope = defaultScope;
}
events.forEach(function (eventName) {
var prefixedEvent = prefix + eventName;
var forwardBroadcast = asyncAngularify(socket, function (data) {
scope.$broadcast(prefixedEvent, data);
});
scope.$on('$destroy', function () {
socket.removeListener(eventName, forwardBroadcast);
});
socket.on(eventName, forwardBroadcast);
});
}
};
And then you just add this next to the others functions :
disconnect: function(){
return socket.disconnect();
},
And voilĂ , there you go :)
You should have something like that :
var wrappedSocket = {
on: addListener,
addListener: addListener,
emit: function (eventName, data, callback) {
return socket.emit(eventName, data, asyncAngularify(socket, callback));
},
disconnect: function(){
return socket.disconnect();
},
removeListener: function () {
return socket.removeListener.apply(socket, arguments);
},
// when socket.on('someEvent', fn (data) { ... }),
// call scope.$broadcast('someEvent', data)
forward: function (events, scope) {
if (events instanceof Array === false) {
events = [events];
}
if (!scope) {
scope = defaultScope;
}
events.forEach(function (eventName) {
var prefixedEvent = prefix + eventName;
var forwardBroadcast = asyncAngularify(socket, function (data) {
scope.$broadcast(prefixedEvent, data);
});
scope.$on('$destroy', function () {
socket.removeListener(eventName, forwardBroadcast);
});
socket.on(eventName, forwardBroadcast);
});
}
};
Just call the RsocketClient.close() method .