当一个函数返回一个promise时,我可以在第一个函数完成它之后调用其他函数:
do_stuff().then(function(){
alert('yoooo');
});
和do_stuff()看起来像这样:
function do_stuff(){
if(!got_the_data){
var d = $.Deferred();
$.ajax({
success: function(html){
$('#box').append(html);
$('#box').addClass('visible');
$('#box').on('transitionend webkitTransitionEnd', function(){
got_the_data = true;
d.resolve();
});
}
});
return d.promise();
}else{
// got the data, what now?
}
}
但如果我已经执行了ajax请求(结果被缓存)并且我不必等待任何事情,我该返回什么?我无法返回d.resolve(),因为附加到then()的函数不会触发:/
我无法返回d.promise,因为我必须解决这个问题。某处
答案 0 :(得分:2)
您可以选择两种方法;缓存数据或缓存承诺。
这里有两个例子,两个关键字都放在url
上,但可以酌情使用任何其他关键字 - 只要它唯一地标识每个个案。
缓存数据
var dataCache = {};
function do_stuff_1(url) {
if(dataCache[url] === undefined) {
return $.ajax({
url: url
}).then(function(data) {
dataCache[url] = data;
return data;
});
} else {
return $.when(dataCache[url]);
}
}
缓存承诺
var promiseCache = {};
function do_stuff_2(url) {
if(!promiseCache[url]) {
promiseCache[url] = $.ajax({
url: url
});
}
return promiseCache[url];
}
在这两种方法中,函数将(禁止未被捕获的错误)返回一个promise,方法是执行$.ajax()
或从缓存中检索数据/ promise。
在大多数应用程序中,几乎没有什么可以区分一种方法与另一种方法。
在缓存可能会变得很大的应用程序中,然后缓存数据并避免缓存promise包装器的开销。
如有必要,可以预先加载缓存,从而避免了获取已知数据的需要:
var dataCache = {
'/path/to/data/a': 'A',
'/path/to/data/b': 'B'
}
或
var promiseCache = {
'/path/to/data/a': $.when('A'),
'/path/to/data/b': $.when('B')
}
答案 1 :(得分:1)
最简单的解决方案是在else
子句中返回一个空的已解析的promise:
return $.Deferred().resolve();
为避免Promise反模式,您的代码可能会更好地构建:
function show_stuff(html) {
return $.Deferred(function(def) {
$('#box').append(html);
$('#box').addClass('visible');
$('#box').on('transitionend webkitTransitionEnd', def.resolve);
});
}
function do_stuff() {
if (got_the_data) {
return $.Deferred().resolve();
} else {
return $.ajax(...).then(show_stuff);
}
}
请注意,没有行(尚)设置got_the_data = true
- 您应该考虑是否真的适合等待数据显示以设置此标志,否则没有什么可以阻止{{1}的多次调用所有导致新内容被添加到do_stuff
。恕我直言,你会用#box
旗帜做得更好。