数组上的 JavaScript .map 并在满足条件时删除项目 [英] JavaScript .map on an array and removing items if condition satisfied
问题描述
我有一个数组 queue
,当对象被修改时,我将对象推送到它.如果用户按下 save
,那么我将遍历 queue
并为它们应用适当的 API 调用.
I have an array queue
that I push objects to it when they are modified. If the user presses save
, then I will loop through the queue
and apply the appropriate API call for them.
如果 API 调用成功,我想从 queue
中删除该项目,否则将其保留在里面并通知用户某些项目未成功保存.我目前有这个(在 AngularJS 中)
If the API call goes through successfully, I want to remove the item from the queue
, otherwise keep it inside and notify the user that some items were not successfully saved. I currently have this (in 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;
});
有没有更好的方法来做到这一点?
Is there a better way of doing this?
推荐答案
您已经在使用 Promise,您可能想要端到端地使用它.此外,您过早地兑现了承诺.
You're already using promises, you might want to do it end-to-end. Also, you're resolving the promise too early.
假设您不想承诺 myCallFunction
本身的次优情况,您仍然应该承诺它.
Assuming the suboptimal case where you don't want to promisify myCallFunction
itself, you should still promisify it.
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;
}
注意,我们在异步函数完成之后解析延迟,而不是在它之前.
Note, we are resolving the defer after the asynchronous function is done, not before it.
现在,我们需要实现一个Settle"函数,它会在所有 Promise 完成时进行解析.这就像 $q.all
,但会等待所有的 promise 来解决而不是实现.
Now, we need to implement a "Settle" function, that resolves when all promises are done no matter what. This is like $q.all
but will wait for all promises to resolve and not fulfill.
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.
}
});
});
}
这种结算函数存在于大多数 promise 实现中,但不存在于 $q
中.我们也可以通过拒绝和 $q.all
来实现这一点,但这意味着流量控制的异常,这是一种不好的做法.
This sort of settle function exists in most promise implementations but not in $q
. We could have also done this with rejections and $q.all
, but that would mean exceptions for flow control which is a bad practice.
现在,我们可以解决
:
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; });
});
这篇关于数组上的 JavaScript .map 并在满足条件时删除项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!