Recently I have been struggling with Long polling in angularJS. I had this code working in the past:
function longPulling(){
$.ajax({
type: "GET",
url: "someScript.php",
async: true,
cache: false,
timeout:50000,
success: function(data){
appendMessage("new", data);
setTimeout(
longPulling,
1000
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
appendMessage("error", textStatus + " (" + errorThrown + ")");
setTimeout(
longPulling,
15000);
}
});
};
$(document).ready(function(){
longPulling();
});
And this worked when I used some php script. Next I wanted this to work in angular and I created the following:
angular.module("WIMT").controller('overviewController', function ($scope,$interval,$http){
$scope.longPolling = function(){
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
$interval(function(){
$scope.longPolling();
},5000)
}, function errorCallback(response) {
$interval(function(){
$scope.longPolling();
},5000)
});
};
$scope.longPolling();
}
For testing purposes I did not include a url and checked the console for 404 errors. I used $interval to set 5 second intervals, the problem with this was that it created multiple threads running the interval (looked like it, correct me if im wrong). So I browsed some StackOverflow topics and tried to apply one of the solutions to my code, looking like this:
angular.module("WIMT").controller('overviewController', function ($scope,$interval,$http){
var promise;
$scope.start = function() {
$scope.stop();
promise = $interval( $scope.longPolling(), 5000);
};
$scope.stop = function() {
$interval.cancel(promise);
};
$scope.longPolling = function(){
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
$scope.start();
}, function errorCallback(response) {
$scope.start();
});
};
$scope.start();
}
The problem with this one is that the interval just doesn't work, it lookes likes its just a regular recursive method that runs thousands of times per seconds. I need to find a solution where I can perform long polling to some url withouth duplicate threads. How can I do this?
Omit the parenthesis and you are fine:
promise = $interval( $scope.longPolling, 5000);
The parenthesis mean "call this function right the way". What $interval expects is a callback, not the result of the function call.
Related
I'm attempting to coax JavaScript into synchronous behaviour, but I've so far failed.
I've tried 30 or more different methods, and here is the latest attempt, based on another answer, here on StackOverflow:
function fnc () {
$.ajax({
type: 'GET',
url: "libraries/resources/data.json",
dataType: 'json',
success: function (data) {
...
objSomething = {
...
};
},
error: function () {}
});
}
fnc().then(function(objSomething) {
google.maps.event.addDomListener(window, 'load', function(){ initialize(objSomething); });
}).catch(function(objSomething) {
...
});
However, I'm getting an error:
TypeError: undefined is not an object (evaluating
'fnc().then')
Most of the methods I've tried have resulted in similar errors.
As for the Google Maps code, it does work (although not always, due to the asynchronous nature of the code execution).
It's worth noting that while I'm able to write complex code from scratch, when it comes to the underlying mechanics, I'm not that proficient.
I'm using jQuery 2.2.2, via the Google API CDN.
This is a solution you are looking for.
function fnc () {
var dfd = jQuery.Deferred();
$.ajax({
type: 'GET',
url: "libraries/resources/data.json",
dataType: 'json',
success: function (data) {
...
objSomething = {
...
};
dfd.resolve(objSomething);
},
error: function (error) { dfd.reject(error); }
});
return dfd.promise();
}
$.when(fnc()).then(function(objSomething) {
google.maps.event.addDomListener(window, 'load', function(){
initialize(objSomething);
});
}, function(error){
//Handle Error
});
use $.ajax function you can use the then function. Refer the following link:
http://wildermuth.com/2013/8/3/JavaScript_Promises
I wanted to be able to send the data from a successful jquery ajax call to other methods in my application because its quite large and it made coding sense to have one api method to work from, so I opted to try out promises. This is my first shot. I am getting some good results but clearly I am still a bit confused on context and timing.
When I run the following code, I am unable to wrap my return data from the ajax call as a jquery object without getting an error:
var widgetSystem={
listenForClick: function(){
$('div').on('click','a',function(){
var $selectTarget = $(this),
widgetid = $(this).data('widgetid');
apiRequestData = widgetSystem.makeApiRequestForSingleWidget(widgetid);
apiRequestData.then(function(result) {
widgetSystem.showWidget(result);
}).catch(function(e) {
console.log('no way big error ' +e);
});
});
},
makeApiRequest: function(widgetid){
return new Promise(function(resolve, reject) {
$.ajax({
method: "POST",
url: "localhost",
dataType: 'json',
data: {
data: {
widgetId: widgetid
},
action: 'apiMethod'
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
reject();
},
success: function (data) {
resolve(data);
}
});
});
},
showWidget: function(data){
$(data).appendTo('body');
//this causes an exception in my apiRequestData.then function in listenForClick
}
}
I am running un minified jquery and getting the following error in my console:
no way big error TypeError: context is undefined
I don't know exactly what your HTML looks like or how the API is set up, but assuming that the API is working correctly and the data sent via POST is correct, I was able to get it working using jsonplaceholder api with the following code (you can find it on JSbin).
var widgetSystem={
listenForClick: function(){
$('div').on('click','a',function(){
console.log('clicked');
var $selectTarget = $(this);
var widgetid = $(this).data('widgetid');
widgetSystem.makeApiRequest(widgetid)
.then(function(result) {
widgetSystem.showWidget(result);
return result;
})
.catch(function(e) {
console.log('no way big error ' +e);
});
});
},
makeApiRequest: function(widgetid){
return new Promise(function(resolve, reject) {
var root = 'http://jsonplaceholder.typicode.com';
$.ajax({
method: "POST",
url: root+'/posts/',
dataType: 'json',
data: {
userId:1,
title:"Havanagila",
body:"Testing the greatness"
},
success: function(xData, status){
resolve(xData);
//reject('whoops');
},
error: function(xhr, status, error){
reject(status);
}
});
});
},
showWidget: function(data){
$('#space').append(document.createTextNode(JSON.stringify(data)));
}
}
widgetSystem.listenForClick()
I don't think there is an issue which how you are calling resolve(data) within the ajax success callback. There may be an issue with the data being sent to your API such that the error callback is called, which in turn calls reject and causes the callback passed to .catch to be called instead of the intended callback passed to .then.
I’m polling S3 every 5 seconds for an image. My polling is successful and I can see it GETs the URL with the image in web inspector. But the function inside of the done() isn’t executing (I can't see anything logging to console):
(function poll() {
setTimeout(function () {
userId = $('#photo').data('user-id');
photoPath = $('#photo').data('photo-path');
$.ajax({
type: 'GET',
dataType: 'json',
url: 'http://s3.amazonaws.com/my_bucket/user-photos/'+userId+'/original/'+photoPath,
done: function (data) {
console.log(data);
$("#photo").append(data);
},
complete: poll
});
}, 5000);
})();
What am I doing wrong?
You're asking for dataType: 'json' but you won't get that back because the server is sending an image.
Are you wanting to show the image in $('#photo')?
(function poll() {
setTimeout(function () {
console.log('polling');
userId = $('#photo').data('user-id');
photoPath = $('#photo').data('photo-path');
$('<img>').on('load', function(){
$('#photo').empty().append(this);
poll();
}).prop('src', 'http://s3.amazonaws.com/my_bucket/user-photos/'+userId+'/original/'+photoPath);
}, 5000);
})();
Demo (with image path replaced by jsfiddle logo)
Below you will see some code to set the currently logged in user for an extjs 4 application. If I have the alert uncommented, the code seems to wait until the alert is accepted before the code continues (it seems). That allows enough time for the asynchronous call to complete with a success. If I comment out the alert, the variable "employeeFilter" never gets set because the AJAX call didn't come back in time. In which case, it sets the "employeeFilter" to null instead. How can I fix this so it waits until the AJAX response comes back in success?
var loggedInUserId = null;
Ext.Ajax.request({
url: '/Controls/UserList/UserService.asmx/GetLoggedInUserId',
method: 'POST',
jsonData: { 'x': 'x' },
success: function (response, opt) {
loggedInUserId = Ext.decode(response.responseText).d;
},
failure: function (response) {
}
});
//alert(loggedInUserId);
var employeeFilter = loggedInUserId;
var projectFilter = '-1';
I would have done this.
var employeeFilter;
Ext.Ajax.request({
url: '/Controls/UserList/UserService.asmx/GetLoggedInUserId',
method: 'POST',
jsonData: { 'x': 'x' },
success: function (response, opt) {
employeeFilter = Ext.decode(response.responseText).d;
//Do here whatever you need to do once the employeeFilter is set. probably call a function and pass the employee filter as parameter.
},
failure: function (response) {
}
});
var projectFilter = '-1';
So currently I use simple try once:
$.getJSON("server.json", function(data) {
servicesList.render(data);
});
I wonder how to try until success each 0.5 seconds?
function getFromServer(){
$.getJSON("server.json", function(data) {
// Verify your data, if it's not you want run error function
if(!data){ onerror(); return; }
servicesList.render(data);
}).error(function() { onerror(); });
}
// if error ,run it again.
function onerror(){
setTimeout(function(){getFromServer();},500);
}
you can find the $.getJSON API help with this link:
http://api.jquery.com/jQuery.getJSON/
Try this logic:
function update_it() {
$.ajax({
url: 'server.json',
dataType: 'json',
success: function(data) {
servicesList.render(data);
},
error: function() {
setTimeout('update_it', 500);
}
});
}
If fail, it waits 500 ms then recalls the function.