I have a fetch() in the callback function of $.post(). The fetch() grabs the data from the backend and updates the collection just fine, however when its time to run either its success or error callbacks, nothing happens! I placed console.log()s in both its callbacks and they never appear in the Javascript console.
Any idea what happened?
A method in a View
create_set: function() {
var self = this;
// Post data to server
$.post('api/create_set', {
user_id: $('#user_id').val(),
post_id: this.post_id,
set_name: $('#new_set_name').val()
}, function() {
// Update list of Sets
self.setList.fetch({
data: {
user_id: $('#user_id').val(),
post_id: this.post_id
},
processData: true
}, {
success: function() {
// Highlight the first class in list
$(self.setListView.el).children('div:first').addClass('active');
console.log('success'); // DOESNT RUN!
}
}, {
error: function() {
console.log('error'); // DOESNT RUN!
}
});
console.log('hello'); // RUNS!
});
}
success and error should be the properties of options object that you pass to fetch, you don't have to create separate objects for them:
self.setList.fetch({
data: {...},
processData: true,
success: function(){...},
error: function(){...}
})
Related
I have to veryfiy the response of the ajax call in my sencha test.
plz advise how to do it.. below is my sample code
beforeEach(()=> {
sim = Ext.ux.ajax.SimManager.init({});
controller = Ext.create('xxxx.controller.Search');
AutoLink = Ext.create('xxxx.model.search.AutoLink', {
objectType: 'myobj'
});
});
it('Should run processResponse when doSearch executes', function() {
const callback = () => {};
sim.register({
'abc.com/myurl.aspx': {
status: 401,
responseText: JSON.stringify({
'success': true,
'data': [{
'autoLink': false, 'status': 'OK', 'objectType': 'Person',
'results': [{ 'ref': 12345, 'managedBy': '01', 'ethnicAppearance': '1', 'gender': '1', 'rules': ['Forename, surname','nickname, DOB']}],
'gridDescriptor': [{'fields': [{'name': 'surname','text': 'Surname','width': 100}],
'sortOrders': ['surname','forename1']
}]
}]
})
}
});
spyOn(controller, 'doSearch'); // internal method which calls the Ext.Ajax
spyOn(controller, 'processResponse'); // internal method which process the response
controller.doSearch(AutoLink, callback, this); // making an ajax call
setTimeout(function () {
expect(controller.processResponse).toHaveBeenCalled();
}, 1000);
});
now when run the test case processResponse gets called, which is fine, but i want to verify the ajax response.
This is how I am doing it:
$.ajax({
url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/getbytitle('Test%203')/items(" + itemId + ")/FieldValuesAsText",
method: 'GET',
headers: {
'accept': 'application/json;odata=verbose'
}
}).then(function (data) {
console.log(data);
}
I don't know if this will help you to achieve exactly what you are looking for. But I would suggest giving it a shot. Then you can go to your console and save the data object to a variable (just for debugging purposes) or just from the console itself look at the object chain and check the data which was returned by your ajax call. So in my case I would find let's say name of the employee here:- data.d.results[0].PreferredName. Then if I want to use it I can just save it in a variable. Make sure you do it in the 'then' function. Here's a sample for save the name to a var:
.then(function (data) {
empName = data.d.results[0].PreferredName;
}
I need to make a server side call when a user does something in the DOM (click a checkbox, select a dropdown, etc. This is the series of events:
User clicks a checkbox (or something)
A spinner fades in and the UI becomes unavailable
The server side call is made, and gets back some JSON
A label in the UI is updated with a value from the JSON
The spinner fades out and the UI becomes available again
The problem I'm having is that 4 and 5 often get reversed, and the spinner fades out sometimes 2 or 3 seconds before the label is updated.
I'm trying to use .when() to make sure this isn't happening, but I don't seem to be doing it right. I've been looking at this thread, and this one, and jquery's own documentation.
Here's where I'm at right now...
function UpdateCampaign() {
$('#overlay').fadeIn();
$.when(SaveCampaign()).done(function () {
$('#overlay').fadeOut();
});
}
function SaveCampaign() {
var formData =
.... // get some data
$.ajax({
url: '/xxxx/xxxx/SaveCampaign',
type: 'GET',
dataType: 'json',
data: { FormData: formData },
success: function (data) {
var obj = $.parseJSON(data);
.... // update a label, set some hidden inputs, etc.
},
error: function (e) {
console.log(e)
}
});
}
Everything works correctly. The server side method is executed, the correct JSON is returned and parsed, and the label is updated as expected.
I just need that dang spinner to wait and fade out until AFTER the label is updated.
The issue is because you're not giving $.when() a promise. In fact you're giving it nullso it executes immediately. You can solve this by returning the promise that $.ajax provides from your SaveCampaign() function like this:
function SaveCampaign() {
var formData = // get some data
return $.ajax({ // < note the 'return' here
url: '/xxxx/xxxx/SaveCampaign',
type: 'GET',
dataType: 'json',
data: { FormData: formData },
success: function (data) {
var obj = $.parseJSON(data);
// update a label, set some hidden inputs, etc.
},
error: function (e) {
console.log(e)
}
});
}
I know its answered by Rory already. But here's mine promise method, it works fine always and instead of using success and error uses done and fail
var jqXhr = $.ajax({
url: "/someurl",
method: "GET",
data: {
a: "a"
});
//Promise method can be used to bind multiple callbacks
if (someConditionIstrue) {
jqXhr
.done(function(data) {
console.log('when condition is true', data);
})
.fail(function(xhr) {
console.log('error callback for true condition', xhr);
});
} else {
jqXhr.done(function(data){
console.log('when condition is false', data);
})
.fail(function(xhr) {
console.log('error callback for false condition', xhr);
});
}
Or if I want a common callback other than conditional ones, can bind directly on jqXhr variable outside the if-else block.
var jqXhr = $.ajax({
url: "/someurl",
method: "GET",
data: {
a: "a"
});
jqXhr
.done(function(data) {
console.log('common callback', data);
})
.fail(function(xhr) {
console.log('error common back', xhr);
});
I am getting some unpredictable behaviour when setting an Ember property in the callback of a custom AJAX function.
The AJAX function is fired in the route as shown below. The success callback updates the property 'session.ajaxStatus' from 'checking' to 'success'. This happens correctly every time a success response is received, and the console logs 'route: success' from the callback function.
The problem is that I am trying to observe and react to that property in a component. Sometimes this observer recognises that 'session.ajaxStatus' has updated from 'checking' to 'success' but sometimes it doesn't.
My guess is that this has to do with how long it takes for the response to be returned. I have wrapped by AJAX function in Ember.run as recommended, to try and ensure that it happens in the Ember run loop.
Is there something I can do to ensure that the observer binding always works, or should I revise the entire pattern?
Route:
session: Ember.inject.service(),
...
actions: {
ajaxRequest: function() {
Ember.run(this, function() {
var self = this;
var url = self.get('session.url');
self.set('session.ajaxStatus', 'checking');
console.log('route: ' + self.get('session.ajaxStatus'));
Ember.$.ajax({
url: url,
type: "GET",
success: function(response) {
console.log('success response');
callBack(response);
},
error: function(response) {
self.set('session.ajaxStatus', 'error');
}
});
callBack = function(jobsInLicense) {
self.set('session.ajaxStatus', 'success');
console.log('route: ' + self.get('session.ajaxStatus'));
//Always logs 'route: success'.
};
});
},
}
Component:
session: Ember.inject.service(),
checkAjaxStatus: function() {
console.log('component: ' + this.get('session.ajaxStatus'));
//Sometimes nothing is logged.
}.observes('session.ajaxStatus'),
If possible you can avoid using observer for this. it depends what actions you are going to perform in checkAjaxStatus
For your question,
Inside route, you don't need to wrap it in Ember.run.
export default Ember.Route.extend({
session: Ember.inject.service(),
actions: {
actions: {
ajaxRequest() {
var self = this;
var url = self.get('session.url');
self.set('session.ajaxStatus', 'checking');
Ember.$.ajax({
url: url,
type: "GET",
}).then(function(response) {
self.set('session.ajaxStatus', 'success');
}, function(jqXHR, textStatus, errorThrown) {
self.set('session.ajaxStatus', 'error');
})
},
}
}
});
And your component code,
session: Ember.inject.service(),
checkAjaxStatus: Ember.observer('session.ajaxStatus', function() {
console.log('component: ' + this.get('session.ajaxStatus'));
//Sometimes nothing is logged.
}),
and include {{session.ajaxStatus}} inside component hbs code.
I tried in twiddle, you can have look into this.
ajax.postJson(
"/foo/GetFoo",
{ fooName: fooName },
function (data) {
},
function (error) { });
};
My Rest api call is GetAsync()
It throws ajax is undefined : JavaScript runtime error: Unable to get property 'exceptionStart' of undefined or null reference. The custom code to make ajax call is below. The api call Getfoo is GetAsync method using attribute HttpGet. Can someone point me to the cause of this failure
var ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->',
postJson: function (url, data, success, error) {
$.ajax(
{
type: "POST",
dateType: "json",
url: url,
data: data,
timeout: ajax.defaultAjaxTimeout,
success: function (result) {
if (success) success(result);
},
error: function (jqXhr, textStatus, errorThrown) {
if (error && jqXhr) {
var responseText = jqXhr.responseText;
var index = responseText.indexOf(ajax.exceptionStart);
if (index > 0) {
var exception = responseText.substr(index + ajax.exceptionStart.length + 1);
index = exception.lastIndexOf(ajax.exceptionEnd);
if (index > 0) {
exception = exception.substr(0, index);
}
error(exception);
} else {
error(errorThrown);
}
}
}
});
},
}
The issue you're having here is that you're attempting to access the variable ajax from a closure before it's created:
var myVariable = {
myProperty: "Hello",
myFunction: function () {
//... access myVariable.myProperty -> error
}
};
There are two options here. The cleaner one, and the one I'd use is this:
var ajaxOptions = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->'
};
var ajax = {
postJson: function (url, data, success, error) {
... ajaxOptions.exceptionStart.length
}
};
The reason this works is because ajaxOptions exists already in the scope where you declare the function ajax.postJson so it's able to reference it correctly from its closure.
The variation on this option is this:
var ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->'
};
ajax.postJson = function (url, data, success, error) {
... ajax.exceptionStart.length
};
The reason this works is because ajax is already declared, and is just attached to the closure of the function.
A second, less-clean option is to put the ajax variable as a child of the window object:
window.ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->',
postJson: function (url, data, success, error) {
... window.ajax.exceptionStart.length
}
};
The reason this works is because window always exists in all lexical scopes, so it'll have no problem referencing it. The reason it's less clean is because it pollutes the window object and any JavaScript anywhere on your page can access and change it, potentially causing unknown behavior. I'm not recommending it, I'm just providing it as an example.
The following steps helped me resolve similar problem, I used IE11
the solution to it in IE 11 can be:
under internet settings select 'Compatibility View settings',
in 'Add this website' enter server name for your website (for example: localhost ), click 'Add' btn.
Tick 'Display intranet steps in Compatibility View' box.
I have found the following script which is apparently written using the javascript framework prototype.
Event.observe(window, 'load', function() {
Event.observe( 'btnSubmit', 'click', purchaseCD);
connectToServer();
});
function connectToServer()
{
new Ajax.Updater(
{ success: 'CD Count', failure: 'errors' },
'server_side.php',
{
method: 'get',
onSuccess: function(transport)
{
if (parseInt(transport.responseText)) connectToServer();
}
});
}
function purchaseCD()
{
new Ajax.Updater(
{ success: 'CD Count', failure: 'errors' },
'server_side.php',
{
method: 'get',
parameters: { num: $('txtQty').getValue() }
});
}
Is anyone here able to convert this script to use jQuery instead of prototype? I don't know prorotype at all so I don't understand it.
Ajax.Updater takes, as parameter 1, two containers into which it will update the successful or failed response of a request to the URL given in parameter 2.
What this script does is that upon page load (I translated it below to DOMReady which is not exactly the same, but jQuery convention) an AJAX request is sent to server_side.php. If it gets a response that it understands, it immediately sends off another request, in order to keep the session alive.
This looks like a terrible design. If you're going to do something like that, you definitely want a timeout between the requests.
Another thing that's not very neat with this script is that every AJAX request is handled by the same page - server_side.php - relying on different parameters for instructions on what action to perform. It would appear cleaner to simply request different pages for different actions.
$(function() {
$('#btnSubmit').click(purchaseCD);
connectToServer();
});
function connectToServer() {
$.ajax({
url: "server_side.php",
success: function(res) {
$('#CD Count').html(res);
if(parseInt(res))
connectToServer();
},
error: function(xhr) {
$('#errors').html(xhr.responseText);
}
});
}
function purchaseCD() {
$.ajax({
url: "server_side.php",
success: function(res) {
$('#CD Count').html(res);
},
data: { num: $('#txtQty').val() },
error: function(xhr) {
$('#errors').html(xhr.responseText);
}
});
}