【问题标题】:$q promise with foreach$q 承诺与 foreach
【发布时间】:2016-06-25 19:23:27
【问题描述】:

我正在编写一个角度服务来处理 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 在第一个项目成功返回后立即返回,而不是等待其余的异步项目调用。非常感谢任何帮助,我对这一切都很陌生。谢谢!

编辑:按要求添加 UpdateListItem 代码:​​

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);
        });
};

【问题讨论】:

    标签: javascript angularjs asynchronous promise angular-promise


    【解决方案1】:

    似乎this.UpdateListItem 函数已经通过拥有$promise 对象返回了承诺。这就是为什么你可以使用.then(chain promise) 函数。

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

    改成

    promises.push(itemPromise)
    

    来自

    promises.push(itemPromise.$promise)
    

    这个问题可能与this answer有关

    【讨论】:

    • 好吧,我这样做了,它逆转了警报。现在是错误!先触发警报,然后触发 IN SUCCESS 警报。更近一点,它现在都在等待它们,但即使其中一项失败,它也总是进入 IN SUCCESS 部分。
    • @NathanKamenar 你能添加this.UpdateListItem 代码吗?任何控制台错误?
    • 我添加了它,是的,有一个错误,但这是预期的。我正在更新 3 个项目进行测试,但我请求更新的项目之一不存在会触发 404 错误
    • 我有另一个我以前从未见过的错字,这是按预期工作的,谢谢。
    • @NathanKamenar 很高兴知道这有帮助.. 谢谢 :-)
    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 2015-05-12
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2015-04-08
    相关资源
    最近更新 更多