Javascript 通用AJAX函数回调未按预期工作
我已经创建了通用ajax函数来使用RESTAPI 我已经写了下面的代码,它可以在一次调用中正常工作。但如果我做了两个不同的调用,那么我的成功回调将被最新的回调覆盖Javascript 通用AJAX函数回调未按预期工作,javascript,jquery,ajax,Javascript,Jquery,Ajax,我已经创建了通用ajax函数来使用RESTAPI 我已经写了下面的代码,它可以在一次调用中正常工作。但如果我做了两个不同的调用,那么我的成功回调将被最新的回调覆盖 var ajax = { parameters: { url: '', dataType: 'json', data: {}, contentType: 'application/json', loading: false, cro
var ajax = {
parameters: {
url: '',
dataType: 'json',
data: {},
contentType: 'application/json',
loading: false,
crossDomain: true,
async: true,
timeout: 30000,
otherData: {}
},
callback: {
success: null,
error: null
},
get: function () {
this.send('GET');
},
post: function () {
this.send('POST');
},
del: function () {
this.send('DELETE');
},
send: function (type) {
self = this;
if (!navigator.userAgent.match(/iPad|iPhone|iPod|android|blackberry|IEMobile/i)) {
this.loadingIcon.show();
if (this.isUndefined(this.parameters.dataType)) this.parameters.dataType = 'json';
if (this.isUndefined(this.parameters.contentType)) this.parameters.contentType = 'application/json';
if (this.isUndefined(this.parameters.loading)) this.parameters.loading = false;
if (this.isUndefined(this.parameters.crossDomain)) this.parameters.crossDomain = true;
if (this.isUndefined(this.parameters.async)) this.parameters.async = true;
if (this.isUndefined(this.parameters.timeout)) this.parameters.timeout = 30000;
if (this.isUndefined(this.callback.error)) this.callback.error = this.defaultError;
return $.ajax({
type: type,
url: this.parameters.url,
dataType: this.parameters.dataType,
data: JSON.stringify(this.parameters.data),
contentType: this.parameters.contentType,
crossDomain: this.parameters.crossDomain,
async: this.parameters.async,
timeout: this.parameters.timeout,
success: function (data) {
var args = arguments[2];
if (!self.isUndefined(self.callback.success)) {
if (self.isUndefined(self.parameters.otherData))
self.callback.success.call(this, data, args.statusText, args);
else
self.callback.success.call(this, data, args.statusText, args, self.parameters.otherData);
}
self.loadingIcon.hide();
},
error: function (xhr, ajaxOptions, thrownError) {
xhrServerObj = xhr;
self.callback.error.call(xhr, ajaxOptions, thrownError);
self.loadingIcon.hide();
}
});
}
},
isUndefined: function (param) {
return (typeof param == 'undefined' || param == null);
},
defaultError: function (data, textStatus, jqXHR) {
},
loadingIcon: {
show: function () {
if (self.parameters.loading) {
console.log('Show loading....');
}
},
hide: function () {
if (self.parameters.loading) {
console.log('Hide loading....');
}
}
}
}
function MyAjax() {
this.parameters = {
url: '',
dataType: 'json',
data: {},
contentType: 'application/json',
loading: false,
crossDomain: true,
async: true,
timeout: 30000,
otherData: {}
};
this.callback = {
success: null,
error: null
};
this.get = function () {
this.send('GET');
};
this.post = function () {
this.send('POST');
};
this.del = function () {
this.send('DELETE');
};
this.isUndefined = function (param) {
return (typeof param == 'undefined' || param == null);
};
this.defaultError = function (data, textStatus, jqXHR) {
};
this.loadingIcon = {
show: function () {
if (self.parameters.loading) {
console.log('Show loading....');
}
},
hide: function () {
if (self.parameters.loading) {
console.log('Hide loading....');
}
}
};
this.send = function (type) {
self = this;
if (!navigator.userAgent.match(/iPad|iPhone|iPod|android|blackberry|IEMobile/i)) {
this.loadingIcon.show();
if (this.isUndefined(this.parameters.dataType)) this.parameters.dataType = 'json';
if (this.isUndefined(this.parameters.contentType)) this.parameters.contentType = 'application/json';
if (this.isUndefined(this.parameters.loading)) this.parameters.loading = false;
if (this.isUndefined(this.parameters.crossDomain)) this.parameters.crossDomain = true;
if (this.isUndefined(this.parameters.async)) this.parameters.async = true;
if (this.isUndefined(this.parameters.timeout)) this.parameters.timeout = 30000;
if (this.isUndefined(this.callback.error)) this.callback.error = this.defaultError;
return $.ajax({
type: type,
url: this.parameters.url,
dataType: this.parameters.dataType,
data: JSON.stringify(this.parameters.data),
contentType: this.parameters.contentType,
crossDomain: this.parameters.crossDomain,
async: this.parameters.async,
timeout: this.parameters.timeout,
success: function (data) {
var args = arguments[2];
if (!self.isUndefined(self.callback.success)) {
if (self.isUndefined(self.parameters.otherData))
self.callback.success.call(this, data, args.statusText, args);
else
self.callback.success.call(this, data, args.statusText, args, self.parameters.otherData);
}
self.loadingIcon.hide();
},
error: function (xhr, ajaxOptions, thrownError) {
xhrServerObj = xhr;
self.callback.error.call(xhr, ajaxOptions, thrownError);
self.loadingIcon.hide();
}
});
}
}
}
我正在使用下面的命令进行ajax调用
getAllStores();
getAllCategory();
function getAllStores() {
var req = Object.create(ajax);
req.parameters = { url: API + '/api/mobileapp/stores' };
req.callback.success = successGetAllStores;
req.get();
}
function successGetAllStores(data) {
$.each(data, function (idx, d) {
$("#StoreId").append($("<option value='" + d.StoreId + "'>" + d.StoreName + "</option>"));
});
}
function getAllCategory() {
var req = Object.create(ajax);
req.parameters = { url: API + '/api/mobileapp/categories' };
req.callback.success = successGetAllCategory;
req.get();
}
function successGetAllCategory(data) {
$.each(data, function (idx, d) {
$("#CategoryId").append($("<option value='" + d.CategoryId + "'>" + d.CategoryName + "</option>"));
});
}
使用下面的调用
var aj1 = new MyAjax();
aj1.parameters = { url: API + '/api/mobileapp/stores' };
aj1.callback.success = successGetAllStores;
aj1.get();
var aj2 = new MyAjax();
aj2.parameters = { url: API + '/api/mobileapp/categories' };
aj2.callback.success = successGetAllCategory;
aj2.get();
我想我可以看出您的问题所在-您在每次调用object.create时都使用相同的对象实例ajax作为原型,因此它们使用共享资源-因此对同一对象的后续调用会互相践踏 执行对象创建时,可以尝试使用$.extend。创建:
var clonedAjax = $.extend(true, {}, ajax);
var req = Object.create(clonedAjax);
然而,处理这段代码的一种更简洁的方法是使用ajax作为一个类,而不是使用object.create
function ajax(){
this.parameters = {
....
};
this.get = function(){};
.....
}
然后
更新:让它工作:从外观上看,这是一个范围问题,下面是一个简化的工作方法示例-关键是在成功发送和使用scb时分配scb。如果这不值得一个绿色勾号,那么什么都不值得;:
JavaScript中最合适的面向对象开发使用函数的原型 因此,首先创建一个函数:
Foo = function()
{
};
然后将函数添加到其原型中,如下所示:
Foo.prototype.Blah = function()
{
// here you can access 'this'
};
现在Blah是名为Foo的对象/类的函数。您可以使用new关键字进行实例化,并按预期调用函数:
var f = new Foo;
f.Blah();
原型也可用于可变成员。JavaScript中有两种类型的变量成员:静态和非静态。如果您使用一个编译器,比如来自Google的闭包编译器,您也可以假装定义public、protected和private成员,但在最终版本中,所有内容都是public的
Foo.static_value = 123; // initialized on load, common to all objects
Foo.prototype.value = 5; // initialized to 5 on construction
在大多数情况下,当静态变量为常量时,您希望使用静态变量
然而,可变成员存在一个陷阱。如果定义对象或数组,则不会复制这些对象或数组,因此相同的引用将显示在所有对象中。在大多数情况下,以下情况是错误的:
Foo.prototype.ary = [1, 2, 3];
Foo.prototype.obj = { a: 1, b: 2, c: 3 };
解决此问题的方法是在构造函数中初始化数组和对象,如下所示:
Foo = function()
{
this.ary = [1, 2, 3];
this.obj = { a: 1, b: 2, c: 3 };
};
Foo.prototype.Blah = function()
{
this.ary.push(17); // not common to all objects of type Foo
};
然后,这些成员的声明使用null:
Foo.prototype.ary = null;
Foo.prototype.obj = null;
这样,您就避免了引用其他对象的问题,这对于您的所有对象来说都是公共的
您可能还希望使用名称空间,它只是一个变量,以避免以后出现潜在问题。假设您的库是call lib,您可以编写:
var lib = {};
然后将其作为所有Foo定义的前缀,如中所示:
lib.Foo = function() { ... };
也有从另一个对象派生一个对象的方法,但这更先进 通过学习如何使用$.extendHank进行解释,可以节省大量代码。我两种方法都试过了,但都不管用。1.使用$.extend时,我遇到一个错误,无法设置未定义的属性“success”。2.使用类函数,其行为与上面的原型对象相同,覆盖了最新的回调函数。更新后包含一个工作示例-如果您不介意一些建议的话-阅读jquery承诺,$.extend和truthy/falsy在评估是否存在某些东西时,您根本不需要这个未定义的函数。此外,如果您想使用这种方法,我建议使用IEFE声明ajax并关闭参数,更好的做法是使用类方法函数ajax{},而不是声明原型并使用object.create。嗯!
var lib = {};
lib.Foo = function() { ... };