Http Request base on priority using AngularJs? - javascript

I am sending multiple http request using Angularjs.
Can we set priority for some requests.
I am keep sending http request according to my need. I can't send request http request on sequence basis
Can somehow we can set priority
Any Idea?
Thanks

Hey id suggest you use a http Intercepter Service there you can monitor every request and response smth like this this is just an idea
.factory('httpInterceptor', function ($q, $rootScope, $filter) {
var canceller = $q.defer();
var numLoadings = 0;
var serialRequests = false;
var timeO;
var time1;
var loadingbar = { loading: "<progress value='?' max='10'></progress>" };
var loadingspinner = { loading: '<ion-spinner icon="crescent"></ion-spinner>' };
return {
request: function (config) {
if (config.url.indexOf('http') > -1 && config.url.indexOf('UpdateDeviceOnlineState') == -1 && config.url.indexOf('maps.googleapis') == -1) {
console.log(config);
//timeout if request takes longer than 15 sec spinner is removed request is cancelled and alert is called
//config.timeout = canceller.promise;
//var time1 = setTimeout(function () {
// canceller.resolve('Unauthorized');
// $rootScope.$broadcast("all_requests_done");
// alert('keine verbindung');
//}, 15000);
numLoadings++;
if (serialRequests == false) {
//if (config.url.indexOf('http') > -1) {
// loadingbar.percent = numLoadings;
// $rootScope.$broadcast("open_requests", loadingbar);
//} else {
// $rootScope.$broadcast("open_requests", loadingspinner);
//}
$rootScope.$broadcast("open_requests", loadingspinner);
} else {
clearTimeout(timeO);
}
}
return config || $q.when(config)
},
response: function (response) {
if (response.config.url.indexOf('http') > -1 && response.config.url.indexOf('UpdateDeviceOnlineState') == -1 && response.config.url.indexOf('maps.googleapis') == -1) {
//clearTimeout(time1);
serialRequests = true;
numLoadings--;
timeO = setTimeout(function () {
serialRequests = false
if ((numLoadings) === 0) {
$rootScope.$broadcast("all_requests_done");
}
});
}
return response || $q.when(response);
},
responseError: function (response) {
if (response.config.url.indexOf('http') > -1 && response.config.url.indexOf('UpdateDeviceOnlineState') == -1 && response.config.url.indexOf('maps.googleapis') == -1) {
serialRequests = true;
numLoadings--;
timeO = setTimeout(function () {
serialRequests = false
if ((numLoadings) === 0) {
$rootScope.$broadcast("all_requests_done");
}
});
}
return $q.reject(response);
}
};
})
But i think you have to work with promises here. $http has a timeout Property, which you can use to prioritize / sort your requests
$http docs for timeout

Related

$.each wait for promise from each object [duplicate]

This question already has answers here:
What is cleanest way to turn Array of JQuery Promises into a JQuery Promise of an Array?
(2 answers)
Closed 6 years ago.
I have another callback/promise issues :-)
I'm trying to implement a series of function each of the function are waiting for a return value from the next one.
I have an ajax call that returns a json on success, in the success
block i'm sending this json to an async function validation.
In validation() I'm loading a script and for each object I sending it to
availability function, i want to wait for the availability to complete and to return value, each value that is return is being
pushed to an array that i want to send it in the end.
I'm having trouble with the callback implementations.
var validArr = [];
function checkStory(callback) {
$.ajax({
url: "",
type: "GET",
data: "",
async: true,
headers: {
Accept: "application/json"
},
success: function(data) {
if (data.isDoc == true) {
_checkDoc(callback);
} else {
if (data.responseObj) {
validation(data.responseObj);
} else {
callback(data.count);
}
}
},
error: function(err) {
console.log("No books");
}
});
}
function validation(responseObj) {
getScript('books.js',
function() {
$.each(responseObj, function(_index, _value) {
var res = aviliabilty(_value);
if (res) {
validArr.push(_index, true);
} else {
validArr.push(_index, false);
}
});
//return after all objects completed execution
return validArr;
}
);
}
function aviliabilty(entry) {
DM.ct.get(entry, function(response) {
if (response) {
for (var idx = 0, adLen = response.ds.length; idx < adLen; idx++) {
var bk = response.ds[idx];
for (var creaIdx = 0, crea = bk.creatives.length; creaIdx < crea; creaIdx++) {
var creative = bk.creatives[creaIdx];
if (creative.type == "line") {
for (var mfIdx = 0, mfLen = creative.Files.length; mfIdx < mfLen; mfIdx++) {
var mediaFile = creative.Files[mfIdx];
if (mediaFile.type == "horror") {
return true;
}
}
} else if (creative.type != "horror") {
return false;
}
}
}
}
});
}
// a function to get the script asynchronously
function getScript(url, success) {
var script = document.createElement('script');
script.src = url;
var head = document.getElementsByTagName('head')[0],
done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
done = true;
success();
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}
Option 1:
use a callback -
validation(data.responseObj, function(){
})
function validation(responseObj, callback) {
//your code....
callback(validArr)
}
Option 2: Use Promises -
validation(data.responseObj).then(function(validArr){
});
function validation(responseObj, callback) {
var defer = Q.defer()
//your code....
defer.resolve(validArr)
return defer.promise
}

infinite scroll duplicate ajax call

I'm having hard time figuring how to avoid duplicate ajax call for my infinite scroll javascript code.
It mostly works but sometimes i have 2 or 3 times the same ajax page call causing a sort of loop.
How to avoid this?
Thanks
//infiniteScroll
var currentPage = 1;
var intervalID = -1000;
var scroll = false;
$('document').ready(function(){
if ( scroll == true) {
if (window.location.pathname == "/" && window.location.search == "" && $('#items_container').length > 0) {
$('.pagination').hide();
intervalID = setInterval(checkScroll, 300);
}
};
})
function checkScroll() {
if (nearBottomOfPage()) {
currentPage++;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
var scroll = false;
$('.spinner').show();
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
var scroll = true;
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
}
},});
}
}
}
function nearBottomOfPage() {
return scrollDistanceFromBottom() < 450;
}
function scrollDistanceFromBottom(argument) {
return pageHeight() - (window.pageYOffset + self.innerHeight);
}
function pageHeight() {
return Math.max(document.body.scrollHeight, document.body.offsetHeight);
}
It looks like the checkScroll function is being called every 300 milliseconds, and it's possible that an AJAX request will take longer than that.
I see you've got the scroll variable, but you are only checking the value of it on the initial document load, which won't affect the timer.
I would suggest having a look at listening to the scroll event instead of creating a timer: jQuery docs. You could then do something like the following to prevent two ajax calls running:
var ajaxRunning = false;
function checkScroll() {
if (!ajaxRunning && nearBottomOfPage()) {
currentPage++;
ajaxRunning = true;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
$('.spinner').show();
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
},
complete: function() {
ajaxRunning = false;
}
},});
}
}
Set async to false, or create a variable like
var isLoading = false;
In before send set it to true. On success set it false again. And before sending the ajax call, check if isLoading isn't true. If it is, return out of the function or put a loop inside with a spinner, which will be checking for the isLoading value so it fires the ajax first after isLoading was set to false.
Example:
function checkScroll() {
if (nearBottomOfPage() && isLoading === false) {
currentPage++;
jQuery.ajax('?page=' + currentPage, {asynchronous:true, evalScripts:true, method:'get',
beforeSend: function(){
var scroll = false;
$('.spinner').show();
isLoading = true;
},
success: function(data, textStatus, jqXHR) {
$('.spinner').hide();
$('#items_container').append(jQuery(data).find('#items_container').html());
var scroll = true;
if(typeof jQuery(data).find('.item').html() == 'undefined' || jQuery(data).find('.item').html().trim().length == 0 || currentPage == 10){
clearInterval(intervalID);
isLoading = false;
}
},
});
}}}

Wait for Infinite Scroll result in Backbone.js View

i have a problem with a InfiniteScrolls calls, this is a part of code in 'Friends' for example:
var InfiniteScrollView = Backbone.View.extend({
el : window,
container : '#profile-friends',
triggerHeight : 10, //px
events : {
'scroll' : 'throttledDetectBottomPage'
},
initialize : function() {
this.throttledDetectBottomPage = _.throttle(this.detectBottomPage, 1000);
},
detectBottomPage : function() {
var self = this;
var offset = $(this.container).height() - this.$el.height() - this.triggerHeight;
if (this.$el.scrollTop() >= offset) {
self.nextPage();
}
},
stop : function() {
this.$el.unbind('scroll');
},
nextPage : function() {
if (this.collection.activeScroll == true) {
this.collection.nextPage();
if (!this.collection.isPaginated) {
if (this.collection.length == 0) {
this.renderNotFoundPage();
this.stop();
return false;
}
} else {
if (this.collection.length == 0) {
this.renderNotFoundMoreResults();
this.stop();
return false;
}
}
}
},
renderNotFoundMoreResults : function() {
$('#profile-friends').append('No more results');
},
renderNotFoundPage : function() {
var container = $(this.container);
container.html('0 results');
}
});
In this.collection.nextPage() is called 'api/friends/pag', pag = page number.
Here the code of the collection:
// profile friends collection
define(
['underscore',
'backbone',
'models/user'],
function(_, Backbone, User){
var PFriendsCollection = Backbone.Collection.extend({
// Reference to this collection's model.
model: User,
initialize: function(){
this.isPaginated = false;
this.active = false;
},
//Call in render
search: function() {
this.page = 1;
this.isPaginated = false;
this.active = true;
this.fetch();
},
//Call in Infinite Scroll view NextPage
nextPage: function() {
if(this.active) {
this.isPaginated = true;
this.page = parseInt(this.page) + 1;
this.fetch({update: true});
}
},
// Url, points to the server API
url: function() {
return 'api/pfriends/' + this.page;
},
// Url, points to the server API
// ATM it is just a json test file
parse: function(response){
// extract items from response.
return response.items;
}
});
return new PFriendsCollection;
});
I created this view in the render() function of FriendsView, and down I surje a problem: i go bottom and trigger launch, but he launch a lot of times if i move the scroll, he call api/pfriends/2, api/pfriends/3, api/friends/4 (For example, is random the number of calls) in the same moment, because he don't wail the first response and launch trigger :(
I do not know where to put a trigger, result or something that blocks the execution of that scroll trigger whenever there pending fetch response.
Thanks =)
fetch returns a jQuery deferred, so you could try this in your collection's nextPage:
return this.fetch({update: true});
Then in your view:
nextPage : function() {
if (this.collection.activeScroll == true && !this.updating) {
var self = this;
this.updating = true;
// function passed to 'always' is called whether the fetch succeeded or failed
this.collection.nextPage().always(function(){
self.updating = false;
if (!self.collection.isPaginated) {
if (self.collection.length == 0) {
self.renderNotFoundPage();
self.stop();
return false;
}
} else {
if (self.collection.length == 0) {
self.renderNotFoundMoreResults();
self.stop();
return false;
}
}
}
}
},
You might want to actually use done and fail instead of always. Check the documentation for more info.

waiting for multiple asynchronous facebook requests

Need to wait for several requests to facebook to complete before taking a final action on the page (updating the count of how many requests returned info) but not sure how to approach it.
How do you check that each function is complete and update a counter before firing a function. window.load is too early unless the page is refreshed after login...?
window.fbAsyncInit = function () {
FB.init({
appId: 'id', // App ID
//channelUrl: '//facebookdev.smithbrosagency.com/LOL/xss_channel.htm', // Channel File
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true // parse XFBML
});
getStatus();
//Subscribe to events
FB.Event.subscribe('auth.statusChange', function (response) { if (response.authResponse) { getStatus(); } });
FB.Event.subscribe('auth.login', function (response) { if (response.status === 'connected') { getStatus(); } });
};
function getStatus() {
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
setPanel('results'); // connected
var accessToken = response.authResponse.accessToken;
var obj = getPermissionsObject(function (permissions) {
getUserInfo(response);
getUserPhotos(response, accessToken);
getFriends(response, accessToken);
getUserLocations(response, accessToken);
getUserMusic(response, accessToken);
getUserMovies(response, accessToken);
});
} else {
setPanel('login'); // not logged in or unauthorized
}
});
}
function getUserPhotos(response, accessToken) {
FB.api('/me/photos?access_token=' + accessToken, function (response) {
var photoList = response.data;
var len = photoList.length;
if (len >= 3) {
var max = 3;
if (len > max) { len = max }; // cap it at 3
for (var i = 0; i < len; i++) {
(function () {
var j = i;
var idx = i + 1;
$('.result2 .option' + idx + ' input').val(photoList[i].picture);
$('.result2 .option' + idx + ' img').attr("src", photoList[i].picture);
})();
}
$('div.result2').addClass("active");
$('#q2 input').val(1); // add to hidden to count results
}
else {
// hide & subtract from total questions
$('div.result2').addClass("inactive");
$('#q2 input').val(0);
}
});
}
$(window).load(function () {
$.when($('#q2 input').val() != '' && $('#q4 input').val() != '' && $('#q5 input').val() != '').then(test());
function test() {
// calc total questions
var total = 0;
$("#Results div input[hidden]").each(function () {
total += $(this).val() * 1;
});
alert(total);
}
});
I'm not sure if I understand you correctly but it seems you need to implement an object like this:
<script type="text/javascript">
//Monitoring object
function RequestStatusMonitor()
{
this.resetRequests();
}
//IDs of the requests you need to monitor
RequestStatusMonitor.prototype.requests=["firstRequest","secondRequest","thirdRequest"];
//Status of the requests
RequestStatusMonitor.prototype.requestsCompleted=[];
//Set all requests to incomplete state
RequestStatusMonitor.prototype.resetRequests = function()
{
this.requestsCompleted = [];
for(var it in this.requests)
{
this.requestsCompleted[this.requests[it]] = false;
}
}
//Set status for a request determined by requestName
RequestStatusMonitor.prototype.setRequestStatus = function(requestName, status)
{
this.requestsCompleted[requestName] = status;
}
//Check if all requests are completed
RequestStatusMonitor.prototype.allRequestsAreCompleted = function()
{
for(var it in this.requestsCompleted)
{
if(!this.requestsCompleted[it])
{
return false;
}
}
return true;
}
//----------------------------------------------------------------------------------
//Usage Example
var monitor = new RequestStatusMonitor();
function onFirstRequestFinished(/*necessary parameters*/)
{
monitor.setRequestStatus("firstRequest", true);
checkCompleted();
}
function onSecondRequestFinished(/*necessary parameters*/)
{
monitor.setRequestStatus("secondRequest", true);
checkCompleted();
}
function onThirdRequestFinished(/*necessary parameters*/)
{
monitor.setRequestStatus("thirdRequest", true);
checkCompleted();
}
function checkCompleted()
{
if(monitor.allRequestsAreCompleted())
{
//Do what you need after all requests are completed
alert("All requests are completed");
}
}
onFirstRequestFinished();
onThirdRequestFinished();
onSecondRequestFinished();
</script>

How to filter out asynchronous requests in ProgressListener?

I am using progresslistener to monitor user actions on web pages, when user click a link, I am trying to check if this request will redirect user to the new location or it is an Ajax WebHttpRequest only (It won't reload or redirect the page). here is the code I am using:
ProgressListener.prototype = {
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports) ) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) {
if (!aRequest) return 0;
if (aFlag & STATE_IS_NETWORK) {
if (aFlag & STATE_START &&
aFlag & STATE_IS_REQUEST &&
aFlag & STATE_IS_DOCUMENT) {
OnLoadInitiated(aWebProgress, aRequest, this.mBrowser);
} else if (aFlag & STATE_STOP &&
aFlag & STATE_IS_WINDOW &&
aStatus == 0) {
OnLoadComplete(aWebProgress, aRequest, this.mBrowser);
}
}
return 0;
},
onLocationChange: function(aProgress, aRequest, aURI)
{
OnLocationChange(aProgress, aRequest, aURI, this.mBrowser);
return 0;
},
onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) { return 0;},
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { return 0;},
onSecurityChange: function(aWebProgress, aRequest, aState) { return 0;}
}
function ProgressListener(aBrowser) {
this.mBrowser = aBrowser;
}
function OnTabOpen(event) {
var doc = event.target.linkedBrowser.contentDocument;
var win = doc.defaultView;
var gsToolbar = new GSToolbar();
gsToolbar.LoadCount = 0;
gsToolbar.JustOpenedTab = true;
var browser = event.target.linkedBrowser;
browser.GSToolbar = gsToolbar;
var pListener = new ProgressListener(browser);
browser.ProgressListener = pListener;
browser.addProgressListener(pListener, NOTIFY_STATE_DOCUMENT);
}
function OnTabMove(event) {
var browser = event.target.linkedBrowser;
}
function OnTabClose(event) {
var browser = event.target.linkedBrowser;
browser.removeProgressListener(browser.ProgressListener);
}
function OnTabSelect(event) {
var browser = event.target.linkedBrowser;
var gsToolbar = gBrowser.getBrowserForDocument(gBrowser.selectedBrowser.contentDocument).GSToolbar;
}
function InitialWindow() {
var num = gBrowser.browsers.length;
if (num == 1) {
var gsToolbar = new GSToolbar();
gsToolbar.LoadCount = 0;
gsToolbar.JustOpenedTab = true;
var browser = gBrowser.getBrowserAtIndex(0);
browser.GSToolbar = gsToolbar;
var pListener = new ProgressListener(browser);
browser.ProgressListener = pListener;
browser.addProgressListener(pListener, NOTIFY_STATE_DOCUMENT);
}
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", OnTabOpen, false);
container.addEventListener("TabMove", OnTabMove, false);
container.addEventListener("TabClose", OnTabClose, false);
container.addEventListener("TabSelect", OnTabSelect, true);
}
function UnloadWindow() {
var num = gBrowser.browsers.length;
if (num == 1) {
var browser = gBrowser.getBrowserAtIndex(0);
browser.removeProgressListener(browser.GSProgressListener);
}
var container = gBrowser.tabContainer;
container.removeEventListener("TabOpen", OnTabOpen, false);
container.removeEventListener("TabMove", OnTabMove, false);
container.removeEventListener("TabClose", OnTabClose, false);
container.removeEventListener("TabSelect", OnTabSelect, false);
}
window.addEventListener("load", function(e){ InitialWindow();}, false);
window.addEventListener("unload", function(e){ UnloadWindow();}, false);
Is there any flag I should check for onStateChange and onLocationChange? Thanks.
I did read the document, but I tried to narrow down the condition to
aFlag & STATE_START && aFlag & STATE_IS_REQUEST && aFlag & STATE_IS_DOCUMENT && aFlag & STATE_IS_WINDOW
but still could not filter out the asynchronous requests. my goal is to make sure my toolbar only deal with the synchronous request (which cause the whole page reloaded or redirected) and by pass any asynchronous calls like Ajax requests.
It seems like I have to add some condition to onStateChange and onLocationChange event, but I tried may combinations of those flags, so far none of them achieve the goal.
What is the best way to handle that?
Thanks a lot for the help.
OK, I got answer from other place.
Compare DOMwindow.top.location.href and aURI.spec in onLocationChange, if those are same, it is synchronous call, otherwise asynchronous.

Categories