[英]JS array.map with costly async function
我有一組用戶。 我需要在每個user.id
上調用“ costlyEncryptionFunction
”,但我不想在同一個user.id
上多次調用“ costlyEncryptionFunction
”。
這是一個工作示例:
const costlyEncryptionFunction = async (id) => {
return new Promise((res) => {
setTimeout(() => {
res(id + 1000)
}, 1000)
})
}
let users = [
{id: 1, item: 1},
{id: 1, item: 2},
{id: 2, item: 5},
{id: 2, item: 6}
]
let currentUserId
users.map(async (user) => {
let encryptedUserId
if(!currentUserId || currentUserId != user.id){
currentUserId = user.id
encryptedUserId = await costlyEncryptionFunction(currentUserId)
}
if(encryptedUserId){
console.log(`inside: ${encryptedUserId} ${user.item} ... do more stuff` )
}
})
output 讀取
inside: 1001 1 ... do more stuff
inside: 1002 5 ... do more stuff
我正在嘗試讓我的 output 讀取:
inside: 1001 1 ... do more stuff
inside: 1001 2 ... do more stuff
inside: 1002 5 ... do more stuff
inside: 1002 6 ... do more stuff
除了調用“ costlyEncryptionFunction
”並多次重復相同的userId
之外,有沒有人對此有解決方案?
最基本的方法是使用 object 作為緩存:
const cache = {};
const costlyEncryptionFunction = async (id) => {
const existing = cache[id];
if (existing) return Promise.resolve(existing);
return new Promise((res) => {
setTimeout(() => {
const encrypted = id + 1000;
cache[id] = encrypted;
res(encrypted);
}, 1000)
})
}
let users = [
{ id: 1, item: 1 },
{ id: 1, item: 2 },
{ id: 2, item: 5 },
{ id: 2, item: 6 }
]
let currentUserId
users.map(async (user) => {
let encryptedUserId
if (!currentUserId || currentUserId != user.id) {
currentUserId = user.id
encryptedUserId = await costlyEncryptionFunction(currentUserId)
}
if (encryptedUserId) {
console.log(`inside: ${encryptedUserId} ${user.item} ... do more stuff`)
}
})
如果您的目標環境支持它,您可以使用Map
:
const cache = new Map();
const costlyEncryptionFunction = async (id) => {
const existing = cache.has(id) ? cache.get(id) : undefined;
if (existing) return Promise.resolve(existing);
return new Promise((res) => {
setTimeout(() => {
const encrypted = id + 1000;
cache.set(id, encrypted) = encrypted;
res(encrypted);
}, 1000)
})
}
let users = [
{ id: 1, item: 1 },
{ id: 1, item: 2 },
{ id: 2, item: 5 },
{ id: 2, item: 6 }
]
let currentUserId
users.map(async (user) => {
let encryptedUserId
if (!currentUserId || currentUserId != user.id) {
currentUserId = user.id
encryptedUserId = await costlyEncryptionFunction(currentUserId)
}
if (encryptedUserId) {
console.log(`inside: ${encryptedUserId} ${user.item} ... do more stuff`)
}
})
這或多或少是實用程序庫在其 memoize 方法的底層所做的,盡管它們通常提供諸如多個參數之類的功能,這使實現有點復雜。
假設您使用的是 Node.js,您可以使用 ramda package 來記憶 function
const {identity, memoizeWith} = require('ramda');
const costlyEncryptionFunction = async (id) => {
return new Promise((res) => {
setTimeout(() => {
res(id + 1000)
}, 1000)
})
}
const memoizedCostlyFunction = (identity, costlyEncryptionFunction)
let users = [
{id: 1, item: 1},
{id: 1, item: 2},
{id: 2, item: 5},
{id: 2, item: 6}
]
let currentUserId
users.map(async (user) => {
let encryptedUserId
if(true ){
currentUserId = user.id
// encryptedUserId = await costlyEncryptionFunction(currentUserId)
encryptedUserId = await memoizedCostlyFunction(currentUserId)
}
if(encryptedUserId){
console.log(`inside: ${encryptedUserId} ${user.item} ... do more stuff` )
}
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.