使用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的原始调用相同的顺序进行调度。

08-04 16:51