使用jQuery Promise,我可以执行以下操作来处理以下情况:我有多个实例需要调用外部资源,但是我不想多次调用同一外部资源。
初始REST调用使我获得了多个数据对象,并带有对附加信息的引用(在示例“部门”属性中提供了对可以在何处找到有关部门的更多信息的引用)。
{
“一些数据”: ”...”,
“部门”:“ https://api.../departments/1000”,
}
我已经深入到每个数据对象的单独函数调用中,希望将所有调用协调到相同的资源。我不想多次获取“部门1000”的部门名称。
我将诺言或返回的结果保存在字典中,然后重用它们。
一个。如果这是一个承诺,我将返回相同的承诺以供调用方重用。
b。如果它是一个获取的值,我将通过使用超时来异步解决Promise。
这是代码:
var Departments = {};
function getDepartmentName(id){
var dfd = new $.Deferred();
var promise = dfd.promise();
if(id in Departments){
if(typeof Departments[id] == 'object'){
return Departments[id];//reuse the promise
}else{//department name is a string
setTimeout(function(){ dfd.resolve(Departments[id]); }, 0);
}
}
else{
Departments[id] = promise;//Set dictionary value to the promise
var dPromise = FetchDepartment('https://api.../departments/'+id);
$.when(dPromise).then(
function(departmentName){
Departments[id] = departmentName;//Re-set dictionary value to the fetched value
dfd.resolve(departmentName);
},
function(err){
delete Departments[id];
dfd.reject('Call failed');
}
);
}
return promise;
}
看来可行,但我担心这是不是一个很棒的设计。我有几个问题。
我应该使用一些诺言功能吗?
是否有任何情况可能以错误的顺序发生?
像这样重用一个Promise实例是否正确?多个调用者都对同一个Promise对象的.then进行了调用,这似乎工作良好,但是我不知道当Promise解决时jQuery如何链接所有这些接收者。
最佳答案
我将诺言或返回的结果保存在字典中,然后重用它们。如果它是一个获取的值,我将通过使用超时来异步解决Promise。
不要这么复杂。这的行为与您仅保留承诺并仅返回承诺的行为完全相同,而不是在最初的承诺完成后为呼叫创建新的承诺。
另外,当您已经在处理诺言时,请输入avoid deferreds。
var Departments = {};
function getDepartmentName(id) {
if (id in Departments){
return Departments[id]; //reuse the promise
} else {
var promise = FetchDepartment('https://api.../departments/'+id).then(null, function(err){
delete Departments[id]; // allow retries
throw err;
});
return Departments[id] = promise;
}
}
重用这样的一个Promise实例是否正确,在该实例中多个调用者对同一个Promise对象的.then进行调用?
是的,这完全可以。他们的回调将按照与
then
的原始调用相同的顺序进行调度。