我现在正在使用jQuery插件开发,我希望在$.ajax
发送之前进行一些预处理操作:
// The signature is the same with $.ajax
$.myAjax = function(url, options) {
var data = options.data;
var promises = [];
for(var name in data) {
if(data.hasOwnProerty(name)) {
var val = data[name];
if(val instanceof File) {
// I want to do some async pre-process here.
var dfd = $.Deferred();
var reader = new FileReader();
reader.onload = function(e) {
data.name = e.target.result;
dfd.resolve();
}
reader.readAsText(val);
promises.push(dfd.promise());
}
}
}
var deferred = $.Deferred();
$.when.apply($, promises).done(function() {
// In fact, I want to return, or wrap cascading this jqXHR
// in the outer function `$.myAjax`.
var jqXHR = $.ajax(url, options).done(function(...) {
// ??? If I want deferred to be a jqXHR like object,
// how to wrap the arguments here?
deferred.resolve(/* Help to fill */);
}).fail(function(...) {
deferred.reject(/* Help to fill */);
});
});
// ** ATTENTION **
// Here, I want to return a jqXHR compatible promise.
// That is what I ask here.
return deferred.promise();
}
我希望在myAjax
中返回一个Deferred对象,或者更确切地说,返回一个jqXHR对象。
这样我就可以使用标准$.ajax
方法调用完全相同的接口:
$.fn.myAjax({...}).done(function(data, textStatus, jqXHR) {
// ...
}).fail(function(jqXHR, textStatus, errorThrown) {
// ...
})
// .always ... etc.
答案 0 :(得分:4)
如果我正确理解你要做的事情,那就无法做到。问题是您的代码在创建jqXHR对象之前从$.myAjax()
返回,因此jqXHR对象无法成为$.myAjax()
函数调用的实际返回对象。您可以从返回的promise中访问它,但返回的promise将是您在ajax调用开始之前创建的一个promise。
仅供参考,您在代码中也有一些承诺反模式,因为您从$.ajax()
处理程序返回$.when()
而不是使用您创建的其他延迟。从.then()
处理程序中返回承诺会自动将承诺链接到原始承诺。
这是您发布的解决方案的清理版本。变更摘要:
.then()
,当jQuery使其承诺标准符合时,不需要更改代码:
// The signature is the same with $.ajax
$.myAjax = function(url, options) {
function readFile(data, name) {
var file = data[name];
if (file instanceof File) {
return $.Deferred(function(dfd) {
var reader = new FileReader();
reader.onload = function(e) {
dfd.resolve(e.target.result);
data[name] = e.target.result;
};
reader.onerror = reader.onabort = dfd.reject;
reader.readAsText(file);
}).promise();
}
}
var data = options.data;
var promises = [];
for(var name in data) {
if(data.hasOwnProerty(name)) {
promises.push(readFile(data, name));
}
}
// trigger when all file fields was loaded.
// so the data were all constructed.
return $.when.apply($, promises).then(function() {
return $.ajax(url, options);
});
}
答案 1 :(得分:-1)
最后,我尝试推断resolveWith
或rejectWith
jqXHR.done()
和jqXHR.fail()
签名的jqXHR.done(function( data, textStatus, jqXHR ) {});
jqXHR.fail(function( jqXHR, textStatus, errorThrown ) {});
jqXHR.always(function( data|jqXHR, textStatus, jqXHR|errorThrown ) {});
或// The signature is the same with $.ajax
$.myAjax = function(url, options) {
var data = options.data;
var promises = [];
for(var name in data) {
if(data.hasOwnProerty(name)) {
var val = data[name];
if(val instanceof File) {
(function(name, val) {
// Deferred for a single field loaded.
var dfd = $.Deferred();
var reader = new FileReader();
reader.onload = function(e) {
data[name] = e.target.result;
dfd.resolve();
}
reader.readAsText(val);
promises.push(dfd.promise());
})(name, val);
}
}
}
// Overall deferred to cascading jqXHR from ajax.
// with returning the same argument list.
var deferred = $.Deferred();
// resolveWith or rejectWith requires a context.
// Thought from the jQuery ajax source code.
var callbackContext = options.context || options;
// trigger when all file fields was loaded.
// so the data were all constructed.
$.when.apply($, promises).done(function() {
// ********** FINAL SOLUTION **********
$.ajax(url, options).done(
function(data, textStatus, jqXHR) {
deferred.resolveWith(context,
[data, textStatus, jqXHR]);
}).fail(
function(jqXHR, textStatus, errorThrown) {
deferred.rejectWith(context,
[jqXHR, textStatus, errorThrown]);
});
});
// So that the resulting promise is well constructed.
return deferred.promise();
}
相同的参数列表。
签名参考:http://api.jquery.com/jQuery.ajax/#jqXHR
$.myAjax
所以整体解决方案是:
$.ajax
所以,现在我们可以使用var dfd = $.myAjax({
url: '...',
// ...
}).done(function(data, textStatus, jqXHR) {
// triggered when the inner ajax done ...
}).fail(function(jqXHR, textStatus, errorThrown) {
// triggered when the inner ajax fail ...
});
功能与Error: Copying file UserUploads\myfiles\Uploads\Images\DSC_2987.jpg to obj\Release\Package\PackageTmp\UserUploads\myfiles\Uploads\Images\DSC_2987.jpg failed. Could not find file 'UserUploads\myfiles\Uploads\Images\DSC_2987.jpg'. CivilContractorMVCApp 0 0 IntelliSense 1
相同:
type
TOnMyExecute = procedure( Sender : TObject ) of object; // sender not required here but is convention
TMyThread = class( TThread )
private
fMyOnExecute : TOnMyExecute;
public
procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp
property MyOnExecute : TMyOnExecute read fMyOnExecute write fMyOnExecute;
end;