数组上的JavaScript .map,如果条件满足则删除项目

Kou*_*sha 6 javascript iteration map promise angularjs

我有一个数组queue,我修改它时将对象推送到它.如果用户按下save,那么我将遍历queue并为它们应用适当的API调用.

如果API调用成功通过,我想从中删除该项queue,否则将其保留在内部并通知用户某些项未成功保存.我目前有这个(在AngularJS中)

var unsuccessfulItems = [];
var promise = queue.map(function(item) {
    var defer = $q.defer();
    myCallFunction( item
           , function( response ) {} // Success
           , function( response ) {  // Error
               unsuccessfulItems.push(item);
           }
    )
    defer.resolve();
    return defer.promise;
})
// Once all items have been processed
$q.all( promise ).then( function() {
    queue = unsuccessfulItems;
});
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?

Ben*_*aum 1

您已经在使用 Promise,您可能想要端到端地执行它。另外,你过早地兑现了承诺。

假设您不想承诺myCallFunction本身的次优情况,您仍然应该承诺它。

function myCall(item){
    var d = $q.defer();
    myCallFunction(item,function(r){ d.resolve({val:r,item:item});}
                       ,function(r){ d.reject(r);});
    return d.promise;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们在异步函数完成之后而不是之前解决延迟。

现在,我们需要实现一个“Settle”函数,无论发生什么情况,它都会在所有 Promise 完成时解析。这就像$q.all但会等待所有承诺解决而不兑现。

function settle(promises){
     var d = $q.defer();
     var counter = 0;
     var results = Array(promises.length);
     promises.forEach(function(p,i){ 
         p.then(function(v){ // add as fulfilled
              results[i] = {state:"fulfilled", promise : p, value: v};
         }).catch(function(r){ // add as rejected
              results[i] = {state:"rejected", promise : p, reason: r};
         }).finally(function(){  // when any promises resolved or failed
             counter++; // notify the counter
             if (counter === promises.length) {
                d.resolve(results); // resolve the deferred.
             }
         });
     });
}
Run Code Online (Sandbox Code Playgroud)

这种解决函数存在于大多数 Promise 实现中,但不存在于$q. 我们也可以通过拒绝和 来做到这一点$q.all,但这意味着流量控制的例外,这是一种不好的做法。

现在,我们可以settle

 settle(queue.map(myCall)).then(function(results){
     var failed = results.filter(function(r){ return r.state === "rejected"; });
     var failedItems = failed.map(function(i){ return i.value.item; });
 });
Run Code Online (Sandbox Code Playgroud)