I need to figure out how to call this function synchronously.
fetchData: function(recs){
store = Ext.getStore('OutOfBalanceList');
store.reload({
params: {
startDate: searchForm.startDate,
endDate: searchForm.endDate,
cusip: searchForm.cusip,
account: searchForm.account
},
callback: function (records, options, success) {
recs = records.length;
return recs;
}
});
},
I appreciate all the sermons about Async, but in this case I have to use Synchronous calls because when the data returned is empty, I have to call back again with different parameters. Presently this ends up being an infinite loop because "recs" is not changed outside!
Many thanks
Don't try and make it synchronous. Do the "call again with different parameters" inside your callback method. Something like this:
fetchData: function(recs) {
var me = this;
store = Ext.getStore('OutOfBalanceList');
store.reload({
params: {
startDate: searchForm.startDate,
endDate: searchForm.endDate,
cusip: searchForm.cusip,
account: searchForm.account
},
callback: function (records, options, success) {
if (records.length == 0) {
me.fetchDataWithDifferentParameters();
}
}
});
}
If you're going to work with JavaScript frameworks and calls to external data sources, then learning how to use callbacks is pretty darn important.
Related
I am using updatingAll method in loopback but it is not working I am not able to understand the reason
I have written something like this
let data = {
isActive: false
};
myModel
.updateAll(data, {
id: {
inq: questionIds
},
});
The order of parameters in updateAll seems to be incorrect. From documentation:
PersistedModel.updateAll([where], data, callback)
Also, it seems a callback function is required.
Callback function called with (err, info) arguments. Required.
So your call should look like this:
let data = {
isActive: false
};
myModel.updateAll({
id: {
inq: questionIds
},
}, data, (err, info) => null); //might want to add error checking to callback function
I am trying to to delay my $http call like this:
githubService.getUserEvents = function getUserEvents() {
return $timeout(
$http.get(ANGULAR_EVENTS).then(function (eventsData) {
return _.map(eventsData.data, function (data) {
return {
type: data.type,
user: data.actor.login,
avatarUrl: data.actor.avatar_url,
createdOn: data.created_at,
repo: data.repo.name
};
});
}),
5000);
};
When I run this it does not seem to perform the delayed request and I cannot see any errors in the chromeconsole? See also here jsbin
How can I call a delayed $http request without using an interceptor?
jsbin
Deleted answer had this right I think, you do need a deferred since you can't return from the $timeout, also as comment indicated needed to inject $timeout service.
githubService.getUserEvents = function getUserEvents() {
var deferred = $q.defer();
$timeout(
function(){
$http.get(ANGULAR_EVENTS).then(function (eventsData) {
deferred.resolve(_.map(eventsData.data, function (data) {
return {
type: data.type,
user: data.actor.login,
avatarUrl: data.actor.avatar_url,
createdOn: data.created_at,
repo: data.repo.name
};
}));
})
},2000);
return deferred.promise;
};
Looks like I went over the public API limit here but should work.
EDIT
Per comments tried with just returning the $timeout promise and it does seem to work here (didn't seem to work when I tried that at first yesterday even after fixing the $timeout, so not sure what was wrong but here's the function working without making an extra deferred object)
githubService.getUserEvents = function getUserEvents() {
return $timeout(function(){
return $http.get(ANGULAR_EVENTS).then(function (eventsData) {
return _.map(eventsData.data, function (data) {
return {
type: data.type,
user: data.actor.login,
avatarUrl: data.actor.avatar_url,
createdOn: data.created_at,
repo: data.repo.name
};
});
})
},2000);
};
Still I have to stand by my point in the comments. So long as you are aware making your own defer is going to have some overhead and you are resolving whatever without going through the whole promise chain then I don't see an issue with doing it the first way (and I find it easier to understand). However just for clarification the $timeout promise does resolve with the value returned from the function it triggers (this makes sense but the docs made it sound as though $timeout resolved the moment the function was triggered not when it was complete... didn't get to the return part of the docs though tbh).
I am using a call to my database to retrieve some results and pushing them onto an array. However when I console.log(this.activeBeers) I don't get an array back but instead an object. How can I get a plain array back instead of a object?
Vue.component('beers', {
template: '#beers-template',
data: function() {
return {
activeBeers: []
}
},
ready: function() {
function getActiveBeers(array, ajax) {
ajax.get('/getbeers/' + $('input#bar-id').val()).then(function (response) {
$.each(response.data, function(key, value) {
array.push(value.id);
});
}, function (response) {
console.log('error getting beers from the pivot table');
});
return array;
}
console.log(this.activeBeers = getActiveBeers(this.activeBeers, this.$http));
},
props: ['beers']
});
AJAX is done asynchronously so you won't be able to just return the value that you do not have yet.
You should console.log your stuff after the $.each to see what you received.
As the other answers pointed out, your getActiveBeers() call is returning before the callback that fills the array gets executed.
The reason your array is an object is because Vue wraps/extends arrays in the underlying data so that it can intercept and react to any mutating methods - like push, pop, sort, etc.
You can log this.activeBeers at the beginning of your ready function to see that it's an object.
By the way, if you want to log the unwrapped/plain array of activeBeers, you can use your component's $log method:
this.$log(this.activeBeers);
The other answer is correct, getActiveBeers sends an HTTP request and then immediately returns the array, it doesn't wait for the ajax request to come back. You need to handle the updating of activeBeers in the success function of the ajax request. You can use the .bind() function to make sure that this in your success function refers to the Vue component, that way you can just push the ids directly into your activeBeers array.
Vue.component('beers', {
template: '#beers-template',
data: function() {
return {
activeBeers: []
}
},
ready: function() {
this.getActiveBeers();
},
methods: {
getActiveBeers: function(){
this.$http.get('/getbeers/' + $('input#bar-id').val()).then(function (response) {
$.each(response.data, function(key, value) {
this.activeBeers.push(value.id);
}.bind(this));
console.log(this.activeBeers);
}.bind(this), function (response) {
console.log('error getting beers from the pivot table');
});
}
}
props: ['beers']
});
I'm just having a play with Vue.js (pretty new to javascript too) and trying to access the events in my Google calendar.
I keep getting 'undefined' when looking in the console.
new Vue({
el: '#app',
data: {
client_id: 'my_client_id',
scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
events: {
title: 'Upcoming Events',
items: [],
}
},
created: function () {
this.loadCalendarApi();
},
methods: {
addEvent: function (event) {
this.events.items.push({
title: event.summary,
date: event.start.dateTime
});
},
loadCalendarApi: function () {
gapi.client.load('calendar', 'v3', this.listUpcomingEvents);
},
listUpcomingEvents: function () {
var request = gapi.client.calendar.events.list({
'calendarId': 'primary',
'timeMin': (new Date()).toISOString(),
'showDeleted': false,
'singleEvents': true,
'maxResults': 10,
'orderBy': 'startTime'
});
var events = this.requestEvents(request);
console.log(events);
},
requestEvents: function (request) {
return request.execute(function (resp) {
resp.items;
});
},
},
});
I think the offending code is somewhere in the requestEvents method.
I also know that 'this.addEvent' is not in scope to be able to refer to the Vue object from inside the request.execute function but I don't know what I need to change.
Can anyone help me or let me know what I'm doing wrong?
Thanks!
Two ways you could do it, one would be to change execute(function) to execute(function, vue) and pass this in as the second argument. Then you could access it like so:
//update your execute function to pass along the vue variable into the response, then
requestEvents: function (request) {
var events = request.execute(function (resp, vue) {
for (i = 0; i < resp.items.length; i++) {
vue.addEvent(resp.items[i]);
}
}, this);
return events;
}
Or if you have jQuery available, you can take a look at $.proxy() which alters a function to use the current context: https://api.jquery.com/jQuery.proxy/
requestEvents: function (request) {
var events = request.execute($.proxy(function (resp) {
for (i = 0; i < resp.items.length; i++) {
this.addEvent(resp.items[i]);
}
}, this));
return events;
}
This way the anonymous response function will be run in the context of your Vue object.
Edit: I found this page as well which shows how you can bind the current context to a function using native JS, jQuery, or Underscore. Any of these would work: https://jsperf.com/bind-vs-jquery-proxy/5
Nowadays you could use the request => {} notation instead of function(request) {} notation, which will pass on the context to the executing method so this.AddEvent() will work as expected.
I started to work with a mobile framework LungoJS. Me and javascript not work quite fine but really i want modify this original code:
ORIGINAL.JS
var mock = function() {
var mock = [];
for (var i=1; i<=5; i++){
mock.push({
id: i,
name: 'name n'+i,
description: 'description n'+i
})
}
lng.View.Template.List.create({
container_id: 'lives',
template_id: 'show_music_template',
data: mock
})
}
return {
mock: mock
}
})(LUNGO, App);
This original code works fine and it's easy, now I want do request using $.get who returns a JSON file and fill array like the ORIGINAL.JS:
JSON RESULT:
{"result":[
{"id":"52","username":"jgali","image":"Prova_(live)387.jpeg","name":"Prova (live)","type":"music","language":"Catalan","category":"8","tags":"indie, dine prova, indie live","description":"Aquesta es una prova online de reidiou","licence":"Reidiou License","played":"54","record_time":"45","facebook_id":"1052266203_2342869925158","twitter_hash":"#Provalive","create_date":"2011-11-01 13:04:21"},
{"id":"52","username":"jgali","image":"Prova_(live)387.jpeg","name":"Prova (live)","type":"music","language":"Catalan","category":"8","tags":"indie, dine prova, indie live","description":"Aquesta es una prova online de reidiou","licence":"Reidiou License","played":"54","record_time":"45","facebook_id":"1052266203_2342869925158","twitter_hash":"#Provalive","create_date":"2011-11-01 13:04:21"}
]}
SERVICE.JS
var mock = function() {
var mock = [];
var url = 'http://localhost/app/rest/podcasts';
var data = {};
//lng.Service.get = $get
lng.Service.get(url, data,function(response) {
var array = [];
//Do something with response
jQuery.each(response.result, function() {
mock.push({
id: this.id,
name: this.name,
description: this.description
})
});
document.write(mock[1].id);
});
lng.View.Template.List.create({
container_id: 'lives',
template_id: 'show_music_template',
data: mock
})
}
return {
mock: mock
}
The problem is outside loop i can't use "mock" array. Sure I make a several mistake...but anybody knows what is the problem?
Thanks.
The problem is that $.get() needs time to execute, and is therefore asynchronous. Asynchronous calls like this involve the use of a callback function. To get access to the mock array you need to nest anything within this callback.
You can also force AJAX calls to be synchronous in jQuery (though I, and the docs, warn against this); according to the docs:
By default, all requests are sent asynchronously (i.e. this is set to
true by default). If you need synchronous requests, set this option to
false. Cross-domain requests and dataType: "jsonp" requests do not
support synchronous operation. Note that synchronous requests may
temporarily lock the browser, disabling any actions while the request
is active.
Thanks!! I solved the problem using callback as you said.
I post the code if anybody are interested:
App.Services = (function(lng, app, undefined) {
var mock = function() {
var mock = new Array();
var url = 'http://localhost/app/rest/podcasts';
var data = {};
function getData (url,data,mock,callbackFnk){
lng.Service.get(url, data,function(response) {
//Do something with response
// now we are calling our own callback function
if(typeof callbackFnk == 'function'){
callbackFnk.call(this, response);
}else{
document.write("Error");
}
});
}
getData(url,data,mock,function(response){
jQuery.each(response.result, function() {
mock.push({
id: this.id,
name: this.name,
description: this.description
})
});
lng.View.Template.List.create({
container_id: 'lives',
template_id: 'show_music_template',
data: mock
})
})
}
return {
mock: mock
}
})(LUNGO, App);