ese*_*elk 44 jquery jquery-deferred
我有一个现有的项目,有很多异步函数返回promises.我正在添加一些缓存,以便在某些情况下异步函数将同步完成,并希望在可能的情况下使此代码更短/更好:
return $.Deferred(function(def) { def.resolve(); }).promise();
Run Code Online (Sandbox Code Playgroud)
例如,我有一个Data Service类来处理大多数看起来像这样的AJAX请求:
function DataService() {
var self = this;
self.makeRequest = function(functionName, data) {
return $.Deferred(function(def) {
var jsonData = JSON.stringify(data);
$.ajax({
type: "POST",
url: "WebService.asmx/" + functionName,
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function(xhr, status, error) {
var ex;
try {
ex = eval("(" + xhr.responseText + ")");
ex.message = ex.Message;
ex.Message = undefined;
} catch (ex2) {
ex = { message: "Invalid Response From Server:\r\n" + xhr.responseText };
}
if (ex.message == "LoginRequired") {
app.viewModels.main.loginRequired(true);
}
else {
app.showError(ex.message);
}
def.reject(ex.message);
}
});
}).promise();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在另一个当前总是调用makeRequest的类中有一个函数:
self.deleteMe = function()
{
return app.dataservice.makeRequest('deleteItem');
}
Run Code Online (Sandbox Code Playgroud)
我想更新deleteMe函数,以便它不总是调用makeRequest,而只是做一些同步工作,然后返回.它需要返回一个承诺,因为无论什么叫做它都会期待,但它需要是一个"已经完成/已解决的承诺".目前我正在使用上面的第一组代码来做到这一点.似乎必须有更好的方法.
Bee*_*oot 50
@Eselk,
根据我的经验,$.Deferred(function(def) {...});很少需要构造,但我想在某些情况下它可能非常有用.
首先, :
return $.Deferred(function(def) { def.resolve(); }).promise();
Run Code Online (Sandbox Code Playgroud)
将简化为:
return $.Deferred().resolve().promise();
Run Code Online (Sandbox Code Playgroud)
其次,DataService.makeRequest()您可以$.Deferred通过利用来避免显式的需要.then(),如下所示:
function DataService() {
var self = this;
self.makeRequest = function (functionName, data) {
return $.ajax({
type: "POST",
url: "WebService.asmx/" + functionName,
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: "json"
}).then(null, function (xhr, status, error) {
var ex;
try {
ex = eval("(" + xhr.responseText + ")");
ex.message = ex.Message;
ex.Message = undefined;
} catch (ex2) {
ex = {
message: "Invalid Response From Server:\r\n" + xhr.responseText
};
}
if (ex.message == "LoginRequired") {
app.viewModels.main.loginRequired(true);
} else {
app.showError(ex.message);
}
return ex.message;
});
};
}
Run Code Online (Sandbox Code Playgroud)
这里的关键方面是:
$.ajax()返回与promise兼容的jqXHR对象,该对象(成功/错误时)立即对其执行操作并进行修改.then()..then(null, ...)- 导致传递新的promise,使用与返回的原始promise相同的值解析$.ajax().因此,在'完成'(即ajax成功)条件下,.then()是完全透明的.return ex.message;- 导致新的承诺被传递,被拒绝ex.message.nett效果应该与原始代码相同,但恕我直言,链接.then()比在$.Deferred()回调中设置所有内容要清晰得多.
顺便说一句,您可以eval("(" + xhr.responseText + ")")通过设置适当的HTTP头服务器端来避免对etc 的需要,使得'.Message'直接显示为失败回调的status参数(或xhr.status?).例如,在PHP中,您可以执行以下操作:
$message = "my custom message";
header("HTTP/1.1 421 $message");
exit(0);
Run Code Online (Sandbox Code Playgroud)
我确信ASP提供相同的功能.
IIRC,任何4xx系列状态代码都可以完成这项工作.421恰好是一个没有特定含义的人.
Gon*_*ing 27
只需return $.when();用来返回已经解决的承诺.
如果你根本没有传递任何参数,jQuery.when()将返回一个已解决的promise.
参考: https ://api.jquery.com/jquery.when/
笔记:
return $.when(undefined);导致以下相当酷的技巧相同,这避免了使用数组和apply.如果您想等待可变数量的promises 并行完成,那么您可以在循环中使用此模式:
var promise; // Undefined is treated as an initial resolved promise by $.when
while (insomeloop){
promise = $.when(promise, newpromise);
}
Run Code Online (Sandbox Code Playgroud)
然后通过以下方式拨打最后一个电话:
promise.then(function(){
// All done!
});
Run Code Online (Sandbox Code Playgroud)
例如
var promise;$.when
var $elements = $('.some-elements');
$elements.each(function(){
var $element = $(this).fadeout();
promise = $.when(promise, $element.promise());
});
promise.then(function(){
// All promises completed!
});
Run Code Online (Sandbox Code Playgroud)
缺点是次要的:
when在新承诺中包含先前的承诺.一个小的开销,你不再需要维护和评估一系列的承诺.| 归档时间: |
|
| 查看次数: |
26196 次 |
| 最近记录: |