Hi I have a base Model -
var BaseModel = Backbone.Model.extend({
initialize : function(input){
// Some base initialization implementation common for all Concrete Models
},
ajaxCall : function(input){
var dfd = new jQuery.Deferred();
$.ajax({
type: 'Get',
url: input.url,
success:function(data){
// Some on success implementation
dfd.resolve(data);
},
error:function(){
dfd.reject();
}
});
return dfd.promise();
}
});
Now, I want to create a ConcreteModel that extends the BaseModel's fetch function and just overrides the ajax success
var ConcreteModel = BaseModel.extend({
ajaxCall : function(input){
BaseModel.prototype.ajaxCall.call(this, input);
// How to override just the ajax success implementation
}
});
How do I just override the ajax success implementation in the ajaxCall function of ConcreteModel.
Thanks.
You can define ajax call successful callback as one of the Base Model method:
var BaseModel = Backbone.Model.extend({
initialize : function(input){
// Some base initialization implementation common for all Concrete Models
},
ajaxCall : function(input){
var dfd = new jQuery.Deferred();
$.ajax({
type: 'Get',
url: input.url,
success:this.onSuccess,
error:function(){
dfd.reject();
}
});
return dfd.promise();
},
onSuccess: function(data){
// Some on success implementation
dfd.resolve(data);
}
});
Then just override the implementation in the onSuccess function of ConcreteModel
var ConcreteModel = BaseModel.extend({
onSuccess: function(data){
alert("hello from concrete mode: "+data);
}
});
You could pass an option second parameter to ajaxCall(input, success) and then within the ajax call have:
$.ajax({
type: 'Get',
url: input.url,
success: $.isFunction(success) ? success : function(data){
// Some on success implementation
dfd.resolve(data);
},
error:function(){
dfd.reject();
}
});
Or you could store the ajax request
this.ajax = $.ajax({...});
And then overwrite it in the ConcreteModel
this.ajax.success(function(){});
Related
I have some js for which I want to write unit test cases using sinon. My js looks like following
var succesHandler = function() {
console.log("yeah success");
};
var failureHandler = function() {
console.log("oops error");
};
var ajaxCall = function(payload, successHandler, failureHandler) {
$.ajax({
type: "POST",
url: "/myUrl",
contentType: 'application/json',
data: JSON.stringify(payload),
success: successHandler,
error: failureHandler
});
};
$('#my-button').live('click', function() {
var dummyPayload = {
"hello" : "coder"
};
ajaxCall(dummyPayload, successHandler, failureHandler);
});
return {
ajaxCall: ajaxCall,
successHandler: successHandler,
failureHandler: failureHandler
};
I want to know how do I spy the ajaxCall() method attached to the #my-button click? Also, how to spy successHandler and failureHandler
i have ajax call inside my function make it reusable, when my ajax success i want to callback a function,
var ajaxPostCall = function(data , url ,callback){
// Return the $.ajax promise
$.ajax({
data: data,
dataType: 'json',
url: url,
method: 'POST',
beforeSend: function() {
onStartAjaxRequest();
},
success:function(data){
if(typeof callback == "function"){
callback();
}else{
console.log('not callback');
}
},
complete: function (XMLHttpRequest, textStatus) {
onEndAjaxRequest();
}
});
}
var ajaxGetCall = function(data , url ,callback){
// Return the $.ajax promise
$.ajax({
url: url,
dataType: 'json',
method: 'GET',
beforeSend: function() {
onStartAjaxRequest();
},
success:function(data){
//console.log('test');
if(typeof callback == "function"){
callback();
}else{
console.log('not callback');
}
},
complete: function (XMLHttpRequest, textStatus) {
onEndAjaxRequest();
}
});
}
function onStartAjaxRequest(){
$('#spinner').hide();
}
function onEndAjaxRequest(){
$('#spinner').show();
}
$(document).ready(function(){
data = {'name' : 'john'};
function callbackSuccess(){
console.log('success');
}
ajaxPostCall(data , '/proccess.php' , function(){
console.log('success 1');
});
ajaxGetCall(data , '/proccessGet.php?id=12' , function(){
console.log('success 2');
});
})
when i run this code, both of ajax post and get can work.but why only my ajaxget can call the callback 'success2' , the ajaxpost doesnt show 'success1' .. any idea?
image
well, i just find out myself and i know the problem...my proccess.php on ajaxpost is not returning json object properly , meanwhile i put dataType: 'json' in my ajaxpost, thats why my ajaxpost is not going to success callback
but i still wonder on my ajaxget still going to success callback even my /proccessGet.php?id=12 does not return json object , is ajax with GETmethod ignoring datatype:json?
I am trying to execute a WCF service call, from function one(). Only once this is complete I want function two() to be executed. The issue I have is that function two() is invoked before function one() completes execution and the WCF service returns the result. How can I solve this please? I am using callback function, so I can't figure out why, given that the response does not exceed 3 seconds.
<script type="text/javascript">
var jsonGetFileResult = "";
function one(callback) {
setTimeout(function() {
//var jsonGetFileResult = "";
console.log('01: into one');
$.ajax({
type: 'GET',
url: ‘http: //wcf.google.com’, //this is the wcf call
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: {},
timeout: 10000,
success: function(data) {
jsonGetFileResult = stringifyNewsletter(data);
console.log('03: ' + jsonGetFileResult);
},
error: function(data) {
alert(error);
}
});
callback();
}, 3000);
}
function stringifyNewsletter(data) {
var removeHeader = JSON.stringify(data);
var file = removeHeader.split('"');
console.log('02: ' + file[3]);
return file[3];
}
function two(linkToNewsletter) {
window.open(linkToNewsletter, '_blank', 'location=yes');
return false;
}
/* now we make use of the callback */
one(function() {
alert(jsonGetFileResult);
// "one" triggers "two" as soon as it is done, note how "two" is a parameter
two(jsonGetFileResult);
});
</script>
You're invoking the callback outside of the ajax "success" function. The $.ajax() call is asynchronous — the call will return to your code essentially immediately, after launching the HTTP request and without waiting for it to finish.
If you move the line
callback();
to inside the "success" handler, then that will run after the HTTP request completes.
You need to put callback inside success function like that:
function one(callback) {
setTimeout(function() {
//var jsonGetFileResult = "";
console.log('01: into one');
$.ajax({
type: 'GET',
url: ‘http: //wcf.google.com’, //this is the wcf call
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: {},
timeout: 10000,
success: function(data) {
jsonGetFileResult = stringifyNewsletter(data);
console.log('03: ' + jsonGetFileResult);
callback();
},
error: function(data) {
alert(error);
}
});
}, 3000);
}
I have the following JS methods:
var foo = function() {
var dfd = $.Deferred();
console.log('foo');
dfd.resolve();
return dfd.promise();
};
var ajaxCall1 = function () {
var dfd = $.Deferred();
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: { },
success: function(response) {
dfd.resolve();
}
});
return dfd.promise();
};
var ajaxCall2 = function () {
var dfd = $.Deferred();
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: {},
success: function (response) {
dfd.resolve();
}
});
return dfd.promise();
};
var ajaxCall3 = function () {
var dfd = $.Deferred();
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: {},
success: function (response) {
dfd.resolve();
}
});
return dfd.promise();
};
and I am calling them via this code:
foo().done(function () {
return ajaxCall1();
}).done(function () {
return ajaxCall2();
}).done(function () {
return ajaxCall3();
});
The issue is that ajaxCall2 is called before the success of ajaxcall1 has occurred. Can you help me fixing this? I need to make ajax calls one by one when success of previous one has occurred.
Use the $.when
var deferredObject = $.ajax({});
$.when(deferredObject)
.then(function(){
var deferredobject2 = $.ajax({});
$.when(deferredobject2)
.then(function(){ alert('after 2nd ajax call');});
});
First of all, you can return the results of the $.ajax calls directly since they are promises already (no need for an intermediate Deferred):
var ajaxCall1 = function () {
return $.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: { }
});
};
var ajaxCall2 = function () {
return $.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: {}
});
};
var ajaxCall3 = function () {
return $.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: 'xxxxxxx',
data: {}
});
};
Second, what you wanna use is .pipe() to effectively chain the calls:
foo().pipe(function () {
return ajaxCall1();
}).pipe(function () {
return ajaxCall2();
}).pipe(function () {
return ajaxCall3();
}).done(function() {
// call1, call2 and call3 done in sequence
}).fail(function() {
// one of the ajax requests failed
});
Simplify.
function foo() {
var dfd = $.Deferred();
console.log('foo');
dfd.resolve();
return dfd.promise();
}
function ajaxCall1() {
return $.ajax({
type: 'POST',
dataType: 'json',
url: 'xxxxxxx',
data: { },
success: function(response) {
console.log('ajaxCall1 success');
}
});
return dfd.promise();
}
// and so on for ajaxCall2 and ajaxCall3
Enhance.
foo().done(function () {
ajaxCall1().done(function () {
ajaxCall2().done(function () {
ajaxCall3();
});
});
});
http://jsfiddle.net/mattball/LxjDS/
Further reading:
How to chain ajax calls using jquery
jQuery Deferred not calling the resolve/done callbacks in order
jQuery deferred - do I need pipes or chains to achieve this pattern?
Same as the other answer except simplifying the callbacks with Frame.js
var responses = [];
for(var i=0; i<1000; i++){
Frame(function(callback){
$.ajax('myserver.api', {
data:i,
type:'post',
complete:function(response) {
responses.push(response);
callback();
}
});
});
}
Frame.start();
Normally, slamming the browser with AJAX requests like this would cause the browser to hang, and the response variables would be returned in the order they are received, rather than the original order they were sent in. Adding Frame to the mix here sorts all that out.
Or you could just use it to flatten out the callbacks:
Frame(function(next){
foo().done(next);
});
Frame(function(next){
ajaxCall1().done(next);
});
Frame(function(next){
ajaxCall2().done(next);
});
Frame(function(next){
ajaxCall3().done(next);
});
Frame(function(next){
//do more stuff
next();
});
Frame.start();
I've had similar problems working heavily with SharePoint web services - you often need to pull data from multiple sources before you're able to continue working.
To solve it I embedded this kind of functionality into my AJAX abstraction library. You can easily define a request which will trigger a set of handlers when complete. However each request can be defined with multiple http calls. Here's the component:
DPAJAX at DepressedPress.com
This very simple example creates one request with three calls and then passes that information, in the call order, to a single handler:
// The handler function
function AddUp(Nums) { alert(Nums[1] + Nums[2] + Nums[3]) };
// Create the pool
myPool = DP_AJAX.createPool();
// Create the request
myRequest = DP_AJAX.createRequest(AddUp);
// Add the calls to the request
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [5,10]);
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [4,6]);
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [7,13]);
// Add the request to the pool
myPool.addRequest(myRequest);
Note that unlike many of the other solutions provided this method does not force single threading of the calls being made - each will still run as quickly as the environment allows but the handler will only be called when all are complete. The component also supports user-defined numbers of requests so you can force single-threading easily if you like. It also supports the setting of timeout values and retry attempts if your service is a little flakey.
I've found it insanely useful (and incredibly simple to understand) for this kind of work.
I created two methods on a Javascript class:
this.saveData = function(){
var url_send = 'm1=1&m2=2'
$.ajax({
url: '/save.php',
dataType : "text",
data:url_send,
type:'POST',
success: function(data) {
// this is does not correct
this.showAcceptBox('error_msg_0');
}
});
};
this.showAcceptBox = function(msg_id){
$('#error_box').removeClass('alert-negative');
$('#error_box').html($('#'+msg_id).html());
$('#error_box').show();
setTimeout(function(){
$('#error_box').fadeOut('slow',function(){
$('#error_box').addClass('alert-negative');
});
},this.message_box_timeout);
};
How do I correct the call method from my class into jQuery .ajax()?
Try to capture this in a closure:
this.saveData = function() {
var url_send = { m1: 1, m2: 2 };
var _self = this;
$.ajax({
url: '/save.php',
dataType : 'text',
data: url_send,
type: 'POST',
success: function(data) {
_self.showAcceptBox('error_msg_0');
}
});
};
or pass it as parameter using the context switch:
this.saveData = function() {
var url_send = { m1: 1, m2: 2 };
$.ajax({
url: '/save.php',
dataType : 'text',
data: url_send,
context: this,
type: 'POST',
success: function(data) {
this.showAcceptBox('error_msg_0');
}
});
};
Quote from the documentation:
context
This object will be made the context of all Ajax-related callbacks. By
default, the context is an object that represents the ajax settings
used in the call ($.ajaxSettings merged with the settings passed to
$.ajax). For example specifying a DOM element as the context will make
that the context for the complete callback of a request, like so:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
$(this).addClass("done");
}
});
i don't see how you give your msg_id :
this.showAcceptBox = function(data){
$('#error_box').removeClass('alert-negative');
$('#error_box').html(data);
$('#error_box').show();
setTimeout(function(){
$('#error_box').fadeOut('slow',function(){
$('#error_box').addClass('alert-negative');
});
},this.message_box_timeout);
};
Or you can retrieve whatever you want in your ajax answer like $('#msg_id',data). Everything depends on what your call is returning.