使用承诺与循环和嵌套函数

Using Promises with Loops and Nested Functions

本文关键字:嵌套 函数 循环 承诺      更新时间:2023-09-26

我正在尝试使用循环和嵌套函数的承诺,其中一些循环。我有一系列函数,它们应该从REST调用中取回SharePoint列表项——一旦这些函数完成执行,那么另一个函数就会被调用,使用被取回的数据。

由于有多个列表,并且每个列表中随后有多个列表项,因此我使用while循环来进行每个REST调用,并从那里将数据(列表项)放入对象中。这些对象被放入数组中,这是第二个函数用来继续执行的对象。

我很难收到承诺的回复。我想有多个承诺被推到一个数组,然后最后使用Promise.all,看看是否一切解决之前使用then。问题是所有的承诺都是pending,因为我没有正确返回resolve

    function onQuerySuccess(sender, args) {
        var itemEnumerator = items.getEnumerator();
        while (itemEnumerator.moveNext()) {
            var promise = new Promise(function (resolve, reject) {
                var item = itemEnumerator.get_current();
                item = item.get_item('URL');
                var itemUrl = item.get_description();
                getRequestItemsFromList(itemUrl);
            });
            promises.push(promise); // all promises are present, but their status is pending
        }
        console.log(promises);
        Promise.all(promises).then(function (val) {
            console.log(val);
            execFuncs(); // function to execute once all the above are done
        }).catch(function (response) {
            console.log(response);
        });
    }

因为涉及到很多函数,所以这是执行顺序:

getRequestItemsFromList //gets url for each list
execCrossDomainRequest (on success call) // makes REST call to get list and its items
cleanData // trims data and puts it in objects

最后是我想我叫Promise.resolve()的地方,因为那是行尾。

无论哪种方式,都不起作用。我检查了其他线程,但我试图在不使用任何库的情况下做到这一点。提前感谢。

编辑:

完整相关代码:

var promises = [];
window.requests = [];
function getRequestLists() {
    var requestsLists = hostWeb.get_lists().getByTitle('Name');  // sharepoint list with all the request list urls.
    context.load(requestsLists);
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml('<View></View>');
    var items = requestsLists.getItems(camlQuery);
    context.load(items, 'Include(URL)');
    context.executeQueryAsync(onQuerySuccess, onQueryFail);
    function onQuerySuccess(sender, args) {
        var itemEnumerator = items.getEnumerator();
        while (itemEnumerator.moveNext()) {
            var promise = new Promise(function (resolve, reject) {
                var item = itemEnumerator.get_current();
                item = item.get_item('URL');
                var itemUrl = item.get_description();
                getRequestItemsFromList(itemUrl);
            });
            promises.push(promise);
        }
        console.log(promises);
        Promise.all(promises).then(function (val) {
            console.log(val);
            execFuncs(); // not shown here
        }).catch(function (response) {
            console.log(response);
        });
    }
    function onQueryFail(sender, args) {
        alert("Request to retrieve list URL items has failed. " + args.get_message());
    }
}
function getRequestItemsFromList(url) {
    var lastPos = getSubstringIndex(url, "/", 4);
    var webUrl = url.substring(0, lastPos); // truncates list url to parse out web url       
    var absListPos = getSubstringIndex(url, "AllItems.aspx", 1);
    var absListUrl = url.substring(0, absListPos); // truncates the AllItems.aspx at the end of the list url
    var relListPos = getSubstringIndex(absListUrl, "/", 3);
    var relListUrl = absListUrl.substring(relListPos, absListUrl.length); // gets the list's relative url 
    var listName = "List Name";
    console.log(webUrl);
    execCrossDomainRequest(webUrl, listName, absListUrl);
}
function execCrossDomainRequest(webUrl, listName, absListUrl) {
    var executor = new SP.RequestExecutor(appWebUrl);
    executor.executeAsync({ // to collect the list description
        url: appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle(@name)?" +
            "@target='" + webUrl + "'&@name='" + listName + "'" +
            "&$select=Description",
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: onCallSuccess,
        error: onCallFail
    });
    function onCallSuccess(data) {
        var json = JSON.parse(data.body);
        var description = json.d.Description;
        executor.executeAsync({ // to collect the list item information
            url: appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle(@name)/items?" +
                "@target='" + webUrl + "'&@name='" + listName + "'" +
                "&$top=500&$select=*," +
                "Assigned_x0020_To/Title" +
                "&$expand=Assigned_x0020_To/Id",
            method: "GET",
            headers: { "Accept": "application/json; odata=verbose" },
            success: onItemsCallSuccess,
            error: onItemsCallFail
        });
        function onItemsCallSuccess(data) {
            var itemsJson = JSON.parse(data.body);
            var results = itemsJson.d.results;
            cleanData(results, description, absListUrl);
        }
        function onItemsCallFail(data, errorCode, errorMessage) {
            console.log("Could not make list items cross domain call. " + errorMessage);
        }
    }
    function onCallFail(data, errorCode, errorMessage) {
        console.log("Could not make list cross domain call. " + errorMessage);
    }
}
function cleanData(results, listDescription, absListUrl) {
    if (!results.length) {
        return;
    }
    for (var i = 0; i < results.length; i++) {
        var client = listDescription;
        var id = results[i].ID;
        ...
        }
        var request = new Request(client, id, path, title, status, estimated, assignedTo, priority, description, response);
        window.requests.push(request);
    }
    return Promise.resolve();
}

当你像这样使用承诺构造函数时:

var promise = new Promise(function (resolve, reject) {

这意味着在这个块中的某个地方,你正在调用resolve和/或reject来解决承诺。

但是你从来没有这样做,让创建的promise对象永远处于挂起状态。

似乎你的承诺数组没有定义:做var承诺= [];