gpt4 book ai didi

javascript - Bluebird.each 如果解决则中断

转载 作者:行者123 更新时间:2023-12-03 05:11:44 24 4
gpt4 key购买 nike

我想测试数组的每个元素,直到满足条件,然后跳过其余的。这是我想出的代码,它似乎有效,但我不确定它是否真的安全或有意想不到的副作用。欢迎其他解决方案。

let buddyAdded = false;
replicaArr = _.keys(ReplicaList);
Promise.each(replicaArr, function(replicaname) {
if (!buddyAdded) {
Player.count({
'buddyList': replicaname
}, function(err, result) {
if (err) {

} else if (result < 990) {

Player.update({
'_id': buddyObj.buddyId
}, {
'buddyList': replicaname
}, function(err) {
if (err) {

} else {
ReplicaList[replicaname].send(buddyObj);
buddyAdded = true;
// success stop here and skip all the other array elements
return;
}
});
}
});
}
});

最佳答案

如果您尝试一次连续枚举一个玩家,并在发现好友列表中有空间的玩家时中止迭代,您可以更新列表并传达发生的任何错误,那么这里有一种方法这样做。

其工作原理如下:

  1. 使用 Bluebird 的 Promise.promisifyAll() 自动为 Player 对象创建 Promise 返回方法,以便我们可以在控制流中使用这些方法。
  2. 使用 Bluebird 的 Promise.mapSeries() 一次连续迭代一个数组。
  3. 链接 Player.countAsync()Player.updateAsync() 方法,以便它们正确排序并从 .mapSeries() 返回它们因此它会等待它们完成,然后再继续迭代到下一个数组元素。
  4. 如果我们找到一个有空间的玩家并成功更新其好友列表,则抛出一个特殊的异常。这将拒绝当前的 promise 链并导致 .mapSeries() 停止其迭代(这就是您所说的您想要的)。
  5. 在更高级别添加一个 .catch() 来测试特殊拒绝并将其转换为成功解决的 promise 。如果是其他错误,则让它继续作为实际错误传播。

代码:

// Promisify the Player object so the methods
// this would usually be done wherever this module is loaded
Player = Promise.promisifyAll(Player);

// create a special subclass of Error for our short circuit
PlayerUpdateDone extends Error {
constructor(name) {
super();
this.name = name;
}
}

// put logic into a function to make it cleaner to use
function addToBuddyList(replicaArr) {

return Promise.mapSeries(replicaArr, function(replicaname) {
return Player.countAsync({buddyList: replicaname}).then(function(result) {
// if room left in buddy list
if (result < 990) {
return Player.updateAsync({'_id': buddyObj.buddyId}, {'buddyList': replicaname}).then(function() {
ReplicaList[replicaname].send(buddyObj);
// throw special exception to abort .mapSeries()
// and stop further processing
throw new PlayerUpdateDone(replicaname);
});
}
});
}).then(function() {
// if it gets here, there were no players with rooms so just return null
return null;
}).catch(function(result) {
// we used a special rejection as a shortcut to stop the mapSeries from executing
// the rest of the series
if (result instanceof PlayerUpdateDone) {
// change this special rejection into a result
return result.name;
}
// must have been regular error so let that propagate
throw result;
});
}

// sample usage
addToBuddyList(replicaArr).then(function(name) {
if (name) {
console.log(`Updated player ${name}`);
} else {
console.log("No players with room in their buddy list");
}
}).catch(function(err) {
// error here
console.log(err);
});
<小时/>

制作自己的定序器可能会更简单,当第一个 promise 解析为真值时停止:

// fn will be passed each array element in sequence
// fn should return a promise that when resolved with a truthy value will stop the iteration
// and that value will be the resolved value of the promise that is returned from this function
// Any rejection will stop the iteration with a rejection
Promise.firstToPassInSequence = function(arr, fn) {
let index = 0;

function next() {
if (index < arr.length) {
return Promise.resolve().then(function() {
// if fn() throws, this will turn into a rejection
// if fn does not return a promise, it is wrapped into a promise
return Promise.resolve(fn(arr[index++])).then(function(val) {
return val ? val : next();
});
});
}
// make sure we always return a promise, even if array is empty
return Promise.resolve(null);
}
return next();
};


Promise.firstToPassInSequence(replicaArr, function(replicaname) {
return Player.countAsync({buddyList: replicaname}).then(function(result) {
// if room left in buddy list
if (result < 990) {
return Player.updateAsync({'_id': buddyObj.buddyId}, {'buddyList': replicaname}).then(function() {
ReplicaList[replicaname].send(buddyObj);
return replicaname;
});
}
});
});

关于javascript - Bluebird.each 如果解决则中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41784895/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com