在转到下一个对象后,让angular.forEach等待承诺

Raz*_*van 17 javascript foreach promise angularjs angular-promise

我有一个对象列表.对象将传递给延迟函数.我想在解析前一个调用后才调用具有下一个对象的函数.有什么方法可以做到这一点吗?

angular.forEach(objects, function (object) {
    // wait for this to resolve and after that move to next object
    doSomething(object);
});
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 24

在ES2017和async/await(参见下面的ES2017中的选项)之前,.forEach()如果您想等待承诺,则无法使用,因为承诺没有阻止.Javascript和promises就是这样不行.

  1. 您可以链接多个承诺并使承诺基础结构对它们进行排序.

  2. 您可以手动迭代并仅在前一个承诺完成时推进迭代.

  3. 您可以使用类似asyncBluebird将为您排序的库.

有很多不同的选择,但.forEach()不会为你做.


这是使用角度承诺的promises链接进行排序的示例(假设objects是一个数组):

objects.reduce(function(p, val) {
    return p.then(function() {
        return doSomething(val);
    });
}, $q.when(true)).then(function(finalResult) {
    // done here
}, function(err) {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

并且,使用标准的ES6承诺,这将是:

objects.reduce(function(p, val) {
    return p.then(function() {
        return doSomething(val);
    });
}, Promise.resolve()).then(function(finalResult) {
    // done here
}, function(err) {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

这是一个手动排序的示例(假设objects是一个数组),虽然这不报告完成或错误,如上面的选项:

function run(objects) {
    var cntr = 0;

    function next() {
        if (cntr < objects.length) {
            doSomething(objects[cntr++]).then(next);
        }
    }
    next();
}
Run Code Online (Sandbox Code Playgroud)

ES2017

在ES2017,该async/wait功能确实允许您使用基于非功能循环,如当"等待"诺言继续循环迭代之前履行forwhile:

async function someFunc() {
    for (object of objects) {
        // wait for this to resolve and after that move to next object
        let result = await doSomething(object);
    }
}
Run Code Online (Sandbox Code Playgroud)

代码必须包含在async函数中,然后您可以使用它await来告诉解释器在继续循环之前等待解析的承诺.请注意,虽然这似乎是"阻塞"类型行为,但它不会阻止事件循环.事件循环中的其他事件仍然可以在处理期间处理await.


小智 10

是的,你可以angular.forEach用来实现这一目标.

这是一个例子(假设objects是一个数组):

// Define the initial promise
var sequence = $q.defer();
sequence.resolve();
sequence = sequence.promise;

angular.forEach(objects, function(val,key){
    sequence = sequence.then(function() {
        return doSomething(val);
    });
});
Run Code Online (Sandbox Code Playgroud)

以下是如何使用array.reduce,类似于@ friend00的答案(假设objects是一个数组):

objects.reduce(function(p, val) {
    // The initial promise object
    if(p.then === undefined) {
        p.resolve(); 
        p = p.promise;
    }
    return p.then(function() {
        return doSomething(val);
    });
}, $q.defer());
Run Code Online (Sandbox Code Playgroud)