如何解决jQuery延迟和异步Ajax请求 -比赛条件?
| 我一直在尝试获取我的Ajax请求以保证加载的模板有响应。 基本上,如果我运行代码以返回延迟的对象,则在拥有模板对象之前将调用$ .then()。这仅在第一次运行时发生。 我要把这根头发撕掉! 我的ajax电话:var ajax = {
getTemplate: (function (id) {
/// <summary>
/// This method when used with $.Deferred fetches a html string
//// containing the template appliciable
/// to the the supplied id.
/// The ajax request object is cached upon the first request and is
/// returned by the cache
/// upon each subsequent request.
/// </summary>
/// <param name=\"id\" type=\"String\">
/// The id that matches the filename to request the template object
/// from.
/// </param>
/// <returns type=\"jqXHR\">
/// A superset of the XMLHTTPRequest object that impliments the
/// promise interface.
/// </param>
var cache = {}; // private cache
// Gets assigned to getTemplate.
return function (id) {
var url = \"/templates/\" + id + \".tpl\";
return cache[id]|| $.ajax({
url: url,dataType: \"html\",success: function (data) {
//ajax.getTemplate(id,data);
cache[id] = data;
},error: function (XMLHttpRequest,textStatus,errorThrown) {
log(\"template request \" + id,XMLHttpRequest,errorThrown);
}
});
};
} ())
};
我在这样的方法中调用此方法:
$.when(ajax.getTemplate(\"tooltip-attributes\")()).then(function (template) {
if (template) {
// Do my template stuff here.
}
});
解决方法
有时我喜欢用我自己的defer来包装ajax调用,因为我不想公开dejared的ajax,而是只根据返回的ajax调用使用一些自定义对象来解决它。例如:
function myFunction(resolved) {
var deferred = $.Deferred();
if ($.IsNullOrEmpty(resolved)) {
deferred.reject(\"Parameters are required.\");
} else {
$.ajax({
type: \"POST\",url: \"/something/somewhere\",data: { someParameter : \"someValue\" },dataType: \"json\"
}).done(function (result) {
if (result.success === false) {
deferred.reject({
success: false,reason: \"you fail\"
});
} else {
deferred.resolve({
success: true,result: result.someData
});
}
});
}
return deferred.promise();
}
然后,我将创建另一个延期的承诺来解决它:
var deferred = $.Deferred(),promise = deferred.promise();
promise
.then(myFunction)
.then(someOtherDependentFunction)
.fail(function (response) {
// do fail stuff
})
.done(function () {
// do done stuff
});
您也可以在此处使用\“ when \\”进行异步,而不是像这样将它们链接起来。
然后解决问题
deferred.resolve({
member: item
});
我之所以喜欢它,是因为它允许我通过使someOtherDependentFunction成为使用解析后的数据并返回promise的任何其他函数来构建动态函数链。显然,还有许多其他方法可以使用此方法。
, 看来您没有正确创建Deferred。
尝试将top函数更改为
// Gets assigned to getTemplate.
return $.Deferred(function (id) {
, 您应该看一下本教程,尤其是“延迟您的延期”部分。关于jQuery.pipe()函数的文档也很有趣!
问题是,在$ .when()中调用的每个函数都需要调用其promise()函数,以便$ .when()等待每个函数的完成。显然从缓存返回对象并不能解决延迟!
首先让您的函数始终返回$ .Deferred对象(例如已经描述过的BonyT),然后让其调用promise()函数:
getTemplate: (function(id) {
return $.Deferred(function (id) {...}
.promise();
})()
您的内部返回值要么提供已存在的缓存对象,要么提供$ .ajax xmlhttp请求。后者总是返回一个Deferred对象,该对象在其.done()回调处理函数中调用.resolve()函数-但是缓存版本却没有!因此,如果要从本地缓存对象中提取数据,则必须手动调用$ .Deferred.resolve()或$ .Deferred.reject()。
getTemplate: (function(id) {
if (cache.hasOwnProperty(id)) {
var dfd = $.Deferred();
var filtered = dfd.pipe(function(value) {
return cache[value];
});
return dfd.resolve(id);
} else {
$.ajax({
url: url,dataType: \"html\"
})
.done(function(result) {
/*fires when resolved*/
return result;
})
.fail(/*fires only when rejected*/)
.always(/*fires when both rejected or resolved*/);
}
})()
顺便说一下,不再使用.success()和.error(),因为它们将在jQuery 1.8 \“ Deprecation notice \”中弃用。请改用.done()、. fail()和.always()。
, 可能让您感到困惑的是,外部的id
和内部的id
...都未分配。
外部的“ 8”实际上可以消失-仅当您在自我执行程序调用中传递了ID时,才会分配外部“ 8”。
现在,实际的解决方法是正确调用内部函数(由ajax.getTemplate()
返回的函数):
$.when(ajax.getTemplate()(\"tooltip-attributes\")).then(...);
请注意,\“ tooltip-attributes \”现在出现在第二组括号中。但是,有一个很好的理由不采用这种方式进行调用-也就是说,每个“ 11”调用都将拥有自己的独立缓存,而不是一个通用缓存。这样做更有意义:
var templateGetter = ajax.getTemplate();//Assign the returned function to make it reusable
...
$.when(templateGetter(\"tooltip-attributes\")).then(...);
我个人认为整个构造令人困惑,并且可能会使用Crockford样式的模块模式,如下所示:
var AJAX = {
var cache = {}; // private cache of jqXHR objects (promises)
var getTemplate = function (id) {
var url = \"/templates/\" + id + \".tpl\";
if(!cache[id]) {
cache[id] = $.ajax({
url: url,dataType: \'html\',error: function (XMLHttpRequest,textStatus,errorThrown) {
log(\"template request \" + id,XMLHttpRequest,errorThrown);
}
});
}
return cache[id];
};
return {
getTemplate: getTemplate
}
};
现在,AJAX.getTemplate()
保证会返还诺言。
AJAX.getTemplate(\"tooltip-attributes\").then(function (template) {
if (template) {
// Do my template stuff here.
}
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。