2016-05-02 22 views
1

我该如何同步运行一系列承诺,以便第二个承诺在第一个承诺完成之前不会执行?我在这里加载三个数据块,每个数据块有10个客户端,然后加载其余的数据块。这里的想法是继续前进,并显示其余的正在加载的前N个客户端。我不想要的是必须明确地说processChunk1()。然后(()=> processChunk2())等,就像我有下面。我希望它在一个循环中处理块,直到没有更多的客户端。任何帮助,将不胜感激!平展同步角度承诺

loadPerformanceDtos(): ng.IPromise<{}> { 
    var deferred = this.$q.defer(); 
    var clientList: any = []; 

    $.extend(clientList, this.$location.search().client); 

    // If the user only searched for one client, we need to turn it into an array 
    if (!angular.isArray(clientList)) { 
     clientList = [clientList]; 
    } 

    var that = this; 

    // Sort so we can chunk it 
    var sortedClients: string[] = (<string[]>clientList).sort(); 
    const chunkSize: number = 10; 

    // Reset page's data 
    this.performanceDtoModels = []; 

    // Set up three chunks to load in order 
    var chunk1: string[] = sortedClients.splice(0, chunkSize); 
    var chunk2: string[] = sortedClients.splice(0, chunkSize); 
    var chunk3: string[] = sortedClients.splice(0, chunkSize); 

    // I don't want to have to explicitly define the groups below, I want this to be in a loop 
    processChunk(chunk1).then(() => { 
     // Resolve the inital page's progress bar 
     deferred.resolve(); 

     processChunk(chunk2).then(() => { 
      processChunk(chunk3).then(() => { 
       processChunk(sortedClients); 
      }); 
     }); 
    }); 

    function processChunk(chunk: string[]) { 
     var chunkDeferred = that.$q.defer(); 
     if (chunk.length === 0) { 
      chunkDeferred.resolve(); 
     } else { 
      that.performanceService.loadPerformanceData(chunk) 
       .success((data: IPerformanceDtoModel[]) => { 
        data.forEach((item: IPerformanceDtoModel) => { 
         // Add the final item to the page 
         that.performanceDtoModels.push(item); 
        }); 

        chunkDeferred.resolve(); 
       }); 
     } 
     return chunkDeferred.promise; 
    } 

    return deferred.promise; 
} 

回答

1

一种方式做到这一点是使用与每个异步操作完成后的原始列表的片段自称是递归函数。以下是一个示例实现。请注意,每次异步操作后,processChunks都会自行调用。

当异步方法失败时,此实现不会考虑。它不包括任何方式来知道所有的块何时完成加载。对于后者,您必须添加一些逻辑来确定最后一个块的加载完成时间。

class YourClass { 

    loadPerformanceDtos(): ng.IPromise<{}> { 
     this.loadDeferred = this.$q.defer(); 

     var requestedClients: string|string[] = this.$location.search().client; 

     var clientList: string[]; 
     if (!angular.isArray(requestedClients)) { 
      clientList = [requestedClients]; 
     } else { 
      clientList = requestedClients; 
     } 

     clientList.sort(); 
     this.performanceDtoModels = []; 
     this.processChunks(clientList, 10); 
    } 

    processChunks(list: string[], size: number) { 
     var chunk = list.slice(0, size); 

     // Resolve the initial page's progress bar 
     if (this.performanceDtoModels.length > 0) { 
      this.loadDeferred.resolve(); 
     } 

     if (chunk.length > 0) { 
      this.processChunk(chunk).then(() => { 
       this.processChunks(list.slice(size), size); 
      }); 
     } 

    } 

    processChunk(chunk: string[]) { 
     var deferred = this.$q.defer(); 

     if (chunk.length === 0) { 
      deferred.resolve(); 
     } 
     else { 
      this.performanceService.loadPerformanceData(chunk) 
       .success((data: IPerformanceDtoModel[]) => { 
        data.forEach((item) => { 
         this.performanceDtoModels.push(item); 
        }); 

       deferred.resolve(); 
      }); 
     } 

     return deferred.promise; 
    } 
} 
+0

这正是我所需要的!我故意忽略了错误处理,并且可以自己处理。我只需要一些方向就可以使其具有通用性,因为我发现所有资源都希望您拥有已知数量的承诺链。 – user2339814