$q承诺与福拉奇

$q promise with foreach

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

我正在编写一个角度服务来处理SharePoint数据,但我遇到了一个问题。我的服务中有一个函数,可以更新和单个项目并返回一个工作正常的$http承诺。问题是我现在正在尝试编写一个函数,该函数利用第一个函数来循环和更新多个项目。我希望它在更新所有项目后返回一个承诺,如果任何项目更新失败,它应该拒绝。这是函数:

this.UpdateListItems = function (webUrl, listName, itemsJson) {
    if (numItems == -1) {
        numItems = itemsJson.length;
        c = 0;
        f = 0;
    }
    var promises = [];
    itemsJson.forEach(function (itemProps) {
        var itemPromise = this.UpdateListItem(webUrl, listName, itemProps.Id, itemProps)
            .then(function (response) {
                c++;
                if (c == numItems && f == 0) {
                    numItems = -1;
                    return itemsJson[listName];
                }
            }, function (error) {
                c++; f++;
                alert("ERROR!");//This gets called first alert below
                if (c == numItems) {
                    numItems = -1;
                    return $q.reject(error);
                }
            });
        promises.push(itemPromise.$promise)
    }, this);
    return $q.all(promises)
        .then(function (data) {
            alert("IN SUCCESS"); //This always gets called immediately after first item success instead of waiting for all items to finish
        }, function (error) {
            alert("IN ERROR"); //This never gets called
        });
};

$q.all 在第一项成功返回后立即返回,而不是等待其余异步项调用。非常感谢任何帮助,我是这一切的新手。谢谢!

编辑:根据要求添加更新列表项代码:

this.UpdateListItem = function (webUrl, listName, itemId, itemProperties) {
    if (typeof lists[listName] === 'undefined') {
        lists[listName] = [];
    }
    var post = angular.copy(itemProperties);
    DataUtilitySvc.ConvertDatesJson(post);
    return this.GetListItemById(webUrl, listName, itemId)
        .then(function (item) {
            return $http({
                url: item.__metadata.uri,
                method: 'POST',
                contentType: 'application/json',
                processData: false,
                headers: {
                    "Accept": "application/json;odata=verbose",
                    "X-HTTP-Method": "MERGE",
                    "If-Match": item.__metadata.etag
                },
                data: JSON.stringify(post),
                dataType: "json",
            }).then(function (response) {
                var temp = [];
                temp.push(itemProperties);
                DataUtilitySvc.MergeByProperty(lists[listName], temp, 'Id');
                return response;
            }, function (error) {
                return $q.reject(error);
            });
        }, function (error) {
            return $q.reject(error);
        });
};

似乎this.UpdateListItem函数已经通过拥有$promise对象返回了承诺。这就是为什么你能够在它上面拥有.then(连锁承诺)功能。

所以基本上你只需要推送返回itemPromise对象,而不是promises数组中itemPromise.$promise。基本上当你做$promise时,它会创建一个[undefined, undefined, ...]数组,并在 for 循环完成后立即解析。

更改为

promises.push(itemPromise)

promises.push(itemPromise.$promise)

这个问题在某种程度上可能与这个答案有关