压扁同步角度承诺

Flatten Synchronous Angular Promises

本文关键字:承诺 同步      更新时间:2023-09-26

如何同步运行一系列promise,以便在第一个promise完成之前不执行第二个promise?在这里,我加载三个数据块,每个数据块有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;
}

实现这一点的一种方法是使用递归函数,该函数在每次异步操作完成后用原始列表的一部分来调用自己。下面是一个示例实现。请注意,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;
    }
}