我的问题:我有一个包含用户和user_hash的数组,需要找到匹配的用户。我想出了以下解决方案:
//results is the array user objects
//safety_first.getUserHash is a function that calculates a user_hash, it retrieves the user-record based on the id and then combines values of some fields and a key and turns this into a hash.
if (results.length > 0)
{
var i = 0;
function checkUserhash(user_id, user_hash, callback) {
safety_first.getUserHash(user_id, function(check_user_hash) {
if (user_hash == check_user_hash)
{
callback(user_id);
}
else
{
if ((i+1) < results.length)
{
i++;
checkUserhash(results[i].id, user_hash, callback);
}
else
{
callback(false);
}
}
});
}
checkUserhash(results[i].id, user_hash, function(user_id) {
if (user_id)
{
console.log("MATCH: "+user_id);
}
else
{
console.log("NO MATCH");
}
});
}
我首先尝试在for循环中执行此操作,但导致它异步调用checkUserhash,当找到匹配项时我无法中断循环。
我正在寻找其他可能的解决方案,请分享您的想法。
问候,彼得
答案 0 :(得分:2)
您可以map
在用户数组上创建一个promise数组。使用Promise.all
等待这些承诺解决,然后遍历响应以检查哈希是否与ID相匹配。
在此示例中,我使用了async
/ await
。我还模拟了一个哈希函数例程,以便您可以实际看到它。只需将解析度从'id'更改为'id + 1',然后重新运行演示程序即可看到Match
变成No match
。
希望这是有用的。
const safety_first = {
getUserHash(id) {
return new Promise(resolve => {
setTimeout(() => resolve(id), 1000);
});
}
}
async function checkUserHashes(userList, promises) {
try {
// await the promises to all resolve
// `Promise.all` preserves the order...
const res = await Promise.all(promises);
// ...which makes it useful if you need to check the returned
// results against the promise-producing array
userList.forEach(({ id }, i) => {
if (id === res[i]) console.log(`${id}|${res[i]} - Match`);
if (id !== res[i]) console.log(`${id}|${res[i]} - No match`);
});
} catch (e) {
console.log(e);
}
};
const userList = [{ id: 1, userHash: 1 }, { id: 2, userHash: 2 }];
// `map` over the fields and return a
// validation promise for each
const promises = userList.map(({ id }) => {
return safety_first.getUserHash(id);
});
// Pass in the original userList, and the generated promises
checkUserHashes(userList, promises);
更新:如果要在找到匹配项后跳出循环,那会容易一些:
const safety_first = {
getUserHash(id) {
return new Promise(resolve => {
// This will match the second object (index 1)
setTimeout(() => resolve(id === 1 ? id: id + 1), 1000);
});
}
}
async function checkUserHashes(userList) {
// iterate over the array of objects
for (let [index, obj] of userList.entries()) {
// await for that one hash check
const res = await safety_first.getUserHash(obj.id);
// if it matches return the id
if (obj.id === res) return obj;
}
// otherwise return null if there are no matches
return null;
}
const userList = [{ id: 0, userHash: 1 }, { id: 1, userHash: 2 }];
(async () => {
const id = await checkUserHashes(userList);
console.log(id);
})();