簡體   English   中英

JS array.map 與昂貴的異步 function

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM