在解决下一个承诺之前,解决$ q.all中每个承诺的整个链

时间:2016-05-11 00:05:28

标签: javascript angularjs

我循环遍历一个数组,并在每个循环中添加一个promises数组,然后传递给$q.all。每个链包含confirm()对话和modal。用户的事件序列应该是confirm() - modal - confirm() - modal。相反,我得到确认() - 确认() - 模态 - 模态。另外,我希望在最后一个模式关闭后执行一个函数refreshSelection(),但它会在最后一个confirm()对话框关闭后立即触发。

    var promiseArr = [];
    var selection = []; // [obj1, obj1, obj3...]

    for (var i = 0; i < selection.length; i++) {
        promiseArr.push(getData(i));
    }

    $q.all(promiseArr)
        .then(refreshSelection);

    function getData(i) {
        var opts = {}; // selection[i].id is param

        return $http(opts)
            .then(onGetSuccess(i));
    }

    function onGetSuccess(i) {
        return function(result) {
            var shouldOpenModal = confirm(selection[i].text);

            if (shouldOpenModal == true) {
                openModal();
            }
        }
    }

    function openModal() {
        var copyPunchesModal = $uibModal.open({
            // modal template options
            }
        });

        copyPunchesModal.result.then(otherFunc, function () {
            console.log("Modal closed");
        });
    }

    function refreshSelection() {
        selection = [];
    }

我也试过以下无济于事。

    //...
    function getData(i) {
        var opts = {}; // selection[i].id is param

        return $http(opts)
            .then(onGetSuccess(i))
            .then(openConfirm)
            .then(openModal);
    }

非常感谢帮助。

3 个答案:

答案 0 :(得分:2)

Q.all没有指定承诺将被解决的顺序。如果你希望按照数组的顺序完成promises,你需要链接promises,以便当前的promise在前一个promise的.then()中执行。

您可以使用reduce来干净利落地完成此任务。

I've got an answer here for ES6 promises,这里适用于Q:

deferred = $q.defer();
deferred.resolve();
return selection.reduce(
    (accumulator, current) => accumulator.then(()=>getData(current)), 
    deferred.promise
);

请注意,您还需要修改getData函数以对象本身进行操作(例如currentSelection.text而不是selection[i].text

答案 1 :(得分:0)

你想使用$ .when函数,它将一些promises作为参数,并在它们全部完成时执行一个函数。或者,如果您可以按顺序完成它们,则可以将它们全部组合在一起。

https://api.jquery.com/jquery.when/

答案 2 :(得分:0)

我想做类似的事情以避免溢出我的程序控制的设备 - 基本上我需要等待异步事务完成才能启动下一个。我使用promises来强制执行顺序,并阻止每个项目完成。

// the async thing we want to do, wrapped in a promise
//
function sendMessage = (message) {
    var promise = new Promise (resolve, reject) {
        // send message via an async function that provides success & fail callbacks, e.g. AJAX
        // replace 'asyncFunction', it's just a placeholder in this example
        asyncFunction (message, 
            function (response) {   // success callback
                if (/*response is to my liking*/) {
                    resolve ();
                } else {
                    reject (new Error (/*why I didn't like the response*/));
                }
            },
            function (error) {  // failure callback
                reject (error);
            }
    };
    return promise;
}

// the array we want to process in order
var myMessages = ['hello', 'world', 'how', 'are', 'you', 'today?'];

// iterator, and recursive function to loop thru array
var idx = 0;
function next () {
    if (idx < myMessages.length) {
        sendMessage (myMessages[idx++]).then (
            next,   // maps to the 'resolve' call in sendMessage
            function (err) {    // maps to the 'reject' calls in sendMessage
                throw err;  // clearly, there's an option to be smarter than this
            }
        )
    }
}

// start the recursion
next ();