You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Promise异常:外层Then提前触发的排查与解决

Fix for Premature .then Execution in SharePoint List Queries with DataTables

Let's break down why your outer .then is firing early, and fix it:

The Root Cause

In your Update 1 code, you correctly created a promises array to track all your asynchronous SharePoint list queries, but you forgot to return that array from the IIFE passed to $q.all. Since $q.all receives undefined instead of a list of promises, it immediately resolves, triggering your DataTables rendering before all queries finish.

The Fixed Code

Here's the corrected version with the critical missing line added:

function GetData(billCycleId, clientCode, jobCodes, engagementCode) {
    var deferred = $q.defer();
    var enhanceFunctions = [
        function(searchResultRow) {
            return spService.AddHyperLinkOnFields(searchResultRow, config.HyperLinks);
        },
        function(searchResultRow) {
            return spService.AddPresenceOnFields(searchResultRow, config.UserFields);
        },
        function(searchResultRow) {
            return spService.FormatDateFields(searchResultRow, config.DateFields, generalConfig.DateTimeFormat);
        },
        function(searchResultRow) {
            return spService.AddImageMapping(searchResultRow, config.ImageFields);
        },
        function(searchResultRow) {
            return spService.FormatNumberFields(searchResultRow, config.NumberFields);
        }
    ];
    var selectProperties = spService.TransformFieldsToSelectProperties(config.Fields);
    var extendedSelectProperties = selectProperties.slice(); // copy array
    var hyperLinkedProperties = spService.TransformFieldsToSelectProperties(config.HyperLinks)
    extendedSelectProperties = extendedSelectProperties.concat(hyperLinkedProperties);
    var result =[];
    spService.GetAllListsFromWeb()
        .then(function (lists) {
            var listEnumerator = lists.getEnumerator();
            return $q.all(
                (function(){
                    var promises = [];
                    while (listEnumerator.moveNext()) {
                        var oList = listEnumerator.get_current();
                        var title = oList.get_title();
                        var id = oList.get_id();
                        if (title.indexOf('Bill Cycles') !== -1) {
                            promises.push(
                                GetRelatedBillCyclesFromList(
                                    id,
                                    extendedSelectProperties,
                                    billCycleId,
                                    clientCode,
                                    jobCodes,
                                    engagementCode,
                                    enhanceFunctions
                                )
                                .then(function (data) {
                                    var trimmedData = spService
                                        .SpSearchQuery
                                        .TrimSearchResultsToSelectProperties(
                                            data,
                                            selectProperties
                                        );
                                    trimmedData.forEach(function(item){
                                        result.push(item);
                                    });
                                })
                            );
                        }
                    }
                    // Critical: Return the array of promises so $q.all can wait for all of them
                    return promises; 
                })()
            );
        })
        .then(function(data){
            var dataTable = $(tableSelector).DataTable();
            dataTable.clear().rows.add(result).columns.adjust().draw();
            vm.ValidDataLoaded = true;
        });
}

Key Fixes Explained

  • Return the promises array: This tells $q.all to wait until every asynchronous query in the array has completed before resolving the promise chain. Without this, $q.all has nothing to wait for and moves to the next .then immediately.
  • Your existing logic for collecting results into the result variable works fine once $q.all properly waits for all queries to finish.

Optional Optimization (Cleaner Result Collection)

If you want to avoid relying on an external result variable, you can use the resolved values from $q.all directly to build your dataset:

.then(function (lists) {
    var listEnumerator = lists.getEnumerator();
    var promises = [];
    while (listEnumerator.moveNext()) {
        var oList = listEnumerator.get_current();
        var title = oList.get_title();
        var id = oList.get_id();
        if (title.indexOf('Bill Cycles') !== -1) {
            promises.push(
                GetRelatedBillCyclesFromList(
                    id,
                    extendedSelectProperties,
                    billCycleId,
                    clientCode,
                    jobCodes,
                    engagementCode,
                    enhanceFunctions
                )
                .then(function (data) {
                    // Return trimmed data directly instead of pushing to external array
                    return spService.SpSearchQuery.TrimSearchResultsToSelectProperties(data, selectProperties);
                })
            );
        }
    }
    // Wait for all promises, then flatten the array of results
    return $q.all(promises).then(function(allTrimmedData) {
        return allTrimmedData.flat(); // Combine all arrays into one
    });
})
.then(function(result){
    var dataTable = $(tableSelector).DataTable();
    dataTable.clear().rows.add(result).columns.adjust().draw();
    vm.ValidDataLoaded = true;
});

This makes the code more predictable by eliminating side effects on external variables.

内容的提问来源于stack exchange,提问作者Luis Valencia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:40:27