I am trying to abort an $https request in Angular when a new request is triggered. However, the request still appears to be pending in Chrome's dev tool. Am I doing anything wrong here?
allMarkersRequest.abort() gets fired when allMarkersRequest is not null. So deferredAbort.resolve() is called, but the program still ends up going through .then().
var allMarkersRequest = null;
function getAllMarkersForSearch() {
if (allMarkersRequest) {
allMarkersRequest.abort();
console.log('Aborting all markers request');
}
var deferredAbort = $q.defer();
var url = Routing.generate('ajax_search_geo_all_markers');
var req = $http({
method: 'POST',
url: url
});
allMarkersRequest = req.then(function (data) {
createMarkers(data.data);
$rootScope.$broadcast('map:markers:updated', markers);
}, function (error) {
// Display error message
});
allMarkersRequest.abort = function() {
deferredAbort.resolve();
};
allMarkersRequest.finally(function () {
allMarkersRequest.abort = angular.noop;
deferredAbort = req = allMarkersRequest = null;
});
}
I did not include the timout parameter in request
var allMarkersRequest = null;
function getAllMarkersForSearch() {
if (allMarkersRequest) {
allMarkersRequest.abort();
console.log('Aborting all markers request');
}
var deferredAbort = $q.defer();
var url = Routing.generate('ajax_search_geo_all_markers');
var req = $http({
method: 'POST',
url: url,
timeout: deferredAbort
});
allMarkersRequest = req.then(function (data) {
createMarkers(data.data);
$rootScope.$broadcast('map:markers:updated', markers);
}, function (error) {
// Display error message
});
allMarkersRequest.abort = function() {
deferredAbort.resolve();
};
allMarkersRequest.finally(function () {
allMarkersRequest.abort = angular.noop;
deferredAbort = req = allMarkersRequest = null;
});
}
Related
I have a list of 15+ ajax requests that need to be called in a specific order. I need each ajax call to wait until the previous function finishes before making the next call. This issue arises because my ajax call, has a direct callback that is also an ajax call.
createCheckIn() {
this.selectedList = [...] // long list of objects
count = 0
for ( i=0; i < this.selectedList.length; i++ ) {
$.ajax({
method: "POST",
url: url,
data: {
check_in: {
client_id: this.selectClient.id,
program_id: this.program_id
}
},
success: function(res) {
that.createWeighIn(count, res.id)
count = count + 1
},
error: function(err) {
console.log(err)
}
})
}
},
createWeighIn(index, check_in_id) {
let data = {}
let that = this
data.weigh_in = this.selectedList[index]
$.ajax({
method: "POST",
url: url,
data: data,
success: function(res) {
console.log(res)
},
error: function(err) {
console.log(err)
}
})
}
the correct data is generated but I believe the ordering is off because eventually there is a call to createCheckIn() that begins before the previous entry has completed.
Is there a way to chain these functions such that createCheckIn() and createWeighIn() are called (and complete) before selectedList iterates.
your for loop in createCheckIn() will not stop to wait on your ajax return. you can do something like:
function createCheckIn(oldI, oldCount){
var count = 0;
var currentI = 0;
if(oldCount != null){
count = oldCount;
}
if(oldI != null){
currentI = oldI;
}
if(currentI < this.selectedList.length){
$.ajax({
method: "POST",
url: url,
data: {
check_in: {
client_id: this.selectClient.id,
program_id: this.program_id
}
},
success: function(res) {
that.createWeighIn(count, res.id)
createCheckIn(currentI + 1, count + 1);
},
error: function(err) {
console.log(err)
}
}); //ajax
} // if
}
seems likely that you can eliminate one of those counters too, the i or the count
Seems like this is missing some potentially really important details about what you need to do leading up to this (ie. this.selectedItems generation) and what happens after (what if one call checkin fails, what if a checkin succeeds but its corresponding weighIn fails, etc..). That said...
It seems you are not actually using the counter for anything other than to reference data you already have, so why not just pass that in directly like:
createWeighIn(weighInData, check_in_id) {
let data = {};
let that = this;
data.weigh_in = weighInData;
// ... your other code
}
I would make createCheckIn only handle doing the ajax request and making a single "reservation" in your system. Then i would make a new method called checkIn that uses the two previous method to process all of selected items:
checkIn() {
let self = this;
let promises = [];
let this.selectedList = [...];
for (let = 0; i < this.selectedList.length; i++) {
// always create the deferred outside the call
let def = $.Deferred();
promises.push(def.promise());
this.createCheckIn().done(function (res) {
self.createWeighIn(self.selectedList[i], res.id))
.done(function () {
// resolve
def.resolve.apply(def, Array.prototype.slice.call(arguments);
})
.fail(function () {
def.reject.apply(def, Array.prototype.slice.call(arguments);
});
}).fail(function () {
// if checkin fails, always reject because we know weighIn wont be called
def.reject.apply(def, Array.prototype.slice.call(arguments);
});
};
// this will resolve/fail when all promises (from createWeighIn) resolve/fail
return $.when.apply(null, promises);
}
so putting it all together:
{
createCheckIn() {
let request = $.ajax({
method: "POST",
url: url,
data: {
check_in: {
client_id: this.selectClient.id,
program_id: this.program_id
}
}
})
.fail(function(err) {
console.log(err)
});
};
return request;
},
createWeighIn(data, check_in_id) {
let params = {};
params.weigh_in = data;
let request = $.ajax({
method: "POST",
url: url,
data: params,
success: function(res) {
console.log(res)
},
error: function(err) {
console.log(err)
}
});
return request;
},
checkIn() {
let self = this;
let promises = [];
let this.selectedList = [...];
for (let = 0; i < this.selectedList.length; i++) {
// always create the deferred outside the call
let def = $.Deferred();
promises.push(def.promise());
this.createCheckIn().done(function (res) {
self.createWeighIn(self.selectedList[i], res.id))
.done(function () {
// resolve
def.resolve.apply(def, Array.prototype.slice.call(arguments);
})
.fail(function () {
def.reject.apply(def, Array.prototype.slice.call(arguments);
});
}).fail(function () {
// if checkin fails, always reject because we know weighIn wont be called
def.reject.apply(def, Array.prototype.slice.call(arguments);
});
};
// this will resolve/fail when all promises (from createWeighIn) resolve/fail
return $.when.apply(null, promises);
}
}
I ended up introducing promises, and some recursion and removing the loop altogether. I basically begin the process by calling createCheckIn() with an index of 0:
this.createCheckIn(0)
createCheckIn(index) {
this.selectedList = [...] // long list of objects
count = 0
let prom = new Promise(function(resolve, reject) {
$.ajax({
method: "POST",
url: url,
data: {
check_in: {
client_id: that.selectClient.id,
program_id: that.program_id
}
},
success: function(res) {
resolve(that.createWeighIn(index, res.id))
},
error: function(err) {
reject(console.log(err))
}
})
})
},
createWeighIn(index, check_in_id) {
let data = {}
let that = this
data.weigh_in = this.selectedList[index]
let prom = new Promise(function(resolve, reject) {
$.ajax({
method: "POST",
url: url,
data: data,
success: function(res) {
console.log(res)
if ( index == (that.selectedList.length - 1) ) {
that.complete = true
resolve(console.log("complete"))
} else {
index++
resolve(that.createCheckIn(index))
}
},
error: function(err) {
console.log(err)
}
})
})
}
I am trying to create an API using a local server for testing. The route
'GET' works fine, however 'POST' has a problem and it is returning 'Cannot GET /add/name'. I am developing the API using node.js and Express. Why am I receiving get when the route is set to 'POST'? Where is the problem?
var fs = require('fs');
var data = fs.readFileSync('events.json');
var allEvents = JSON.parse(data);
console.log(allEvents);
console.log('Server running.');
var express = require('express');
var app = express();
var sever = app.listen(3000, listening);
function listening() {
console.log('Serving...');
}
app.use(express.static('website'));
//GET and send all data from JSON
app.get('/all', sendAll);
function sendAll(request, response) {
response.send(allEvents);
}
//POST new data to JSON
app.post('/add/:name', addData);
function addData(request, response) {
var newData = request.params;
var name = newData.name;
var eventType = newData.eventType;
var reply;
// var newEvent = {
// name: ":name",
// eventType: ":eventType",
// };
var newData = JSON.stringify(allEvents, null, 2);
fs.writeFile('events.json', newData, finished);
function finished(err) {
console.log('Writting');
console.log(err);
var reply = {
word: word,
score: score,
status: 'Success'
}
response.send(reply);
}
}
Request
$(function() {
//HTML
var $list = $('#list');
var jsonURL = '../events.json'
$.ajax({
type: 'GET',
url: '/all',
success: function(data) {
console.log('Data received', data);
$.each(data, function (type, string) {
$list.append('<li>' + type + " : " + string + '</li>');
});
},
error: function (err) {
console.log('Error, data not sent.', err);
}
});
$('#submit').on('click', function () {
// var newEvent = {
// name: $name.val(),
// eventType: $eventType.val(),
// };
var name = $('#fieldName').val();
var eventType = $('#fieldEventType').val();
console.log(name);
$.ajax({
type: 'PUT',
url: '/add/' + name,
success: function (addData) {
$list.append('<li>name: ' + name + '</li>');
},
error: function (err) {
console.log('Error saving order', err);
}
});
});
});
Thank you in advance.
For testing POST request, you can use Postman to test it. If you use the browser to call the api, it will be GET method instead of POST.
I am trying to send the http response as a JSON body to an error handler if an error occurs. I am not really sure how to do this as I am a little inexperienced in this area. Here is the relevant code that I have currently:
Controller:
for (var prop in $scope.applicants) {
var applicant = $scope.applicants[prop];
$scope.sendApplicantsToSR(applicant).then(null, $scope.sendATSError.bind(null, applicant));
}
$scope.sendATSError = function (applicant, error) {
return AtsintegrationsService.applicantErrorHandling(applicant.dataset.atsApplicantID);
};
$scope.sendApplicantsToSR = function(applicant) {
return AtsintegrationsService.sendApplicantsToSR(applicant);
};
Service:
srvc.sendApplicantsToSR = function (applicant) {
var applicantURL = {snip};
return $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
url: applicantURL,
data: applicant
});
};
srvc.applicantErrorHandling = function (applicantID, error) {
var url = srvc.url + {snip};
return $http({
method: 'POST',
url: url,
data: { "error_message": error }
});
};
So, ideally, I would like to pass the result of $scope.sendApplicantsToSR to $scope.sendATSError only when an error occurs.
Inside your controller
YourService.getdatafromservice().then(function(SDetails) {
//response from service
console.log(SDetails);
});
Inside your service
return {
getData: getData
};
function getData() {
var req = $http.post('get_school_data.php', {
id: 'id_value',
});
return req.then(handleSuccess, handleError);
function handleSuccess(response) {
response_data = response.data;
return response_data;
}
function handleError(response) {
console.log("Request Err: ");
}
}
I'm banging my head for not learning from the basics and just jumping in.
I'm building an API that returns the SSL Certificate status of a domain.
It's working fine on console.log but the JSON output is empty, obviously because the exports get executed before the https request ends.
How do I incorporate the exports in response.on(end) function?
Thanks a lot!
function getSSL(domain) {
var options = {
host: 'www.'+domain+'.com',
method: 'get',
path: '/'
};
var isAuth = false;
callback = function(response) {
response.on('data', function () {
isAuth = response.socket.authorized;
});
response.on('end', function () {
console.log(isAuth);
});
}
var req = https.request(options, callback).end();
}
exports.findByDomain = function (req, response) {
var id = req.params.id;
sslCheck = getSSL(id);
response.send(sslCheck);
};
Yes, the response.send(sslCheck); gets executed before getSSL(id); has a chance to finish. You need to send in a callback so it can be executed after getSSL(id); finishes:
function getSSL(domain, callback) {
var options = {
host: 'www.'+domain+'.com',
method: 'get',
path: '/'
};
var isAuth = false;
var httpCallback = function(response) {
response.on('data', function () {
isAuth = response.socket.authorized;
});
response.on('end', function () {
console.log(isAuth);
callback(isAuth);
});
}
var req = https.request(options, httpCallback).end();
}
exports.findByDomain = function (req, response) {
var id = req.params.id;
getSSL(id, function(sslCheck) {
response.send(sslCheck);
});
};
I've got a call using Resource in angularjs but i get some problems because i can't abort every calls it does. This kind of structure i use for an autocomplete.. is it possible convert from resource call to http? This is the code
var Resource = $resource(URL, {},{ getAutocompleteResults: { method: "GET", params: {text: ""} }});
var locked = false;
function getMoreData() {
if(locked)
return;
locked = true;
Resource.autoCompleteResults()
.$promise.then(function(data) {
$scope.autocompleteViewResults = data;
locked = false;
});
}
This is what i've tried so far with no success.
$scope.autocompleteViewResults = function () {
$http
.get(URL, {
params: {
text = ""
}
})
.success(function (data) {
$scope.autocompleteViewResults = data;
});
};
Or if someone knows an alternative method..
The $scope.autocompleteViewResults variable is being assigned 2 times.
Try this:
$scope.autocompleteViewResults = {};
$scope.getResults = function(valueAsTyped) {
$http
.get(URL, {
params: {
text: valueAsTyped
}
})
.success(function (data) {
$scope.autocompleteViewResults = data;
});
};
Update
If you need to cancel old requests.
var promiseCanceller = $q.defer();
$scope.autocompleteViewResults = {};
$scope.getResults = function(valueAsTyped) {
promiseCanceller.resolve('request cancelled'); // cancel currently running request
$http
.get(URL, {
params: {
text: valueAsTyped
},
timeout: promiseCanceller.promise // pass promiseCanceller as the timeout
})
.success(function (data) {
$scope.autocompleteViewResults = data;
});
};