【问题标题】:Memoize callback function记忆回调函数
【发布时间】:2020-09-26 11:26:15
【问题描述】:

我正在尝试这个备忘录

function getData(n, m, callback){
    callback(n+m);
};
let memoizedData = memoize(getData);
console.log(memoizedData(5, 4, (result)=>{})) // 9;

我想缓存结果,即 9,所以每当下次调用发生时,它都会从缓存中获取。 如果 getData 将返回 n+m 而不是放入回调,我理解记忆。 任何帮助将不胜感激。

编辑:想通过 vanillaJs 来实现。 为更清楚起见,编辑了上述问题

function getData(n, m, callback){
    callback(n+m);
};
let memoizedData = memoize(getData);
memoizedData(5, 4, (result)=>{console.log(result)}) // 9;
memoizedData(5, 4, (result)=>{console.log(result)}) // 9 - returned from cache

【问题讨论】:

  • 有没有写函数memoize的尝试?您在尝试时遇到了什么问题?当getData 不返回任何内容而是调用回调时,您为什么期望console.log 打印任何有用的信息?
  • 我没完全理解,但是你在寻找如何实现记忆吗?
  • 是的,我尝试过,但遇到了回调问题。 @trincot
  • 是的,带有这个回调的东西。我能够通过返回 n+m 的 getSomeData 实现相同的功能。 @GermanOchea

标签: javascript memoization


【解决方案1】:

如果我理解正确,您要求的是memoize 的实现。至于你的console.log:这很奇怪,因为结果不是返回,而是作为参数传递给回调。因此,您实际上应该在该回调中进行打印。你甚至可以通过console.log 作为回调。

对于memoize的实现,我假设要记忆的函数总是有一个回调作为最后一个参数。

首先,memoize 应该返回一个函数,该函数接受与被记忆的函数相同的参数。

这个想法是维护一个 Map,由传递给函数的参数(不包括回调参数)和相应的结果作为键。构建密钥的一种方法是形成参数的 JSON 表示。

memoize 被调用,并且参数形成一个已经存在于映射中的键时,然后使用映射中的相应值调用回调。如果不存在,则使用相同的参数集调用函数,回调除外。让回调是一个将结果存储在地图中的函数,然后将结果传递给传递给memoize的回调。

你可以这样写:

function memoize(func) {
    let map = new Map; // for memoization
    return function(...args) {
        let callback = args.pop(); // last argument must be a function
        let key = JSON.stringify(args);
        let result = map.get(key);
        if (result !== undefined) {
            console.log(`getting result from map.get('${key}')`);
            return callback(result);
        }
        console.log(`calling ${func.name}(${args.join(", ")}, callback)`);
        func(...args, result => {
            console.log(`writing result with map.set('${key}', ${result})`);
            map.set(key, result);
            callback(result);
        });
    }
}

function getData(n, m, callback){
    callback(n+m);
}
let memoizedData = memoize(getData);


memoizedData(5, 4, console.log) // 9 calling getData;
memoizedData(5, 4, console.log) // 9 from memory;

请注意:

memoizedData(5, 4, console.log)

...只是“短”:

memoizedData(5, 4, (result) => console.log(result))

唯一的区别是console.log 周围有一个额外的包装函数,但实际上并没有真正的区别。

【讨论】:

  • 好的,我从这个答案中了解了很多,老实说,我想要这样的东西,但如果我的 memoizedData 将是 ``` memoizedData(5, 4, (result)=>{console.log ("结果", 结果)}) ```
  • 您希望memoizedData 是递归的吗?你能描述更多你在这里寻找的东西吗?您是在谈论使用更详细的回调参数调用memoizedData 的最后一行吗?当然可以。你看有什么问题吗?请参阅对我的答案的编辑。
  • 哦,是的,我知道这会起作用,非常感谢@trincot。非常感谢。
  • 只是好奇你提到递归memoizedData ,你是不是碰巧遇到了一些问题,想分享一下。 @trincot
  • 不,这只是您上面第一条评论的措辞。这让我很困惑,就好像你是在定义 memoizedData 本身。但后来我意识到你只是在谈论如何调用它,而不是define它。
【解决方案2】:

如果你问如何实现 memoization,你可以这样实现

import { useMemo, useCallback } from 'react';

export default function Index() {
  const getData = useCallback((n, m, callback) => callback(n + m), []);

  let memoizedData = useMemo(() => getData(5, 4, (result) => result), [
    getData,
  ]);
  console.log(memoizedData);
  return null;
}

【讨论】:

  • 非常感谢分享,但我忘了提到我正在尝试通过 vanillaJs 解决这个问题。立即添加编辑
猜你喜欢
  • 2014-06-02
  • 2022-12-07
  • 2022-06-17
  • 1970-01-01
  • 2010-12-04
  • 2021-03-30
  • 2020-11-07
  • 2018-09-18
  • 1970-01-01
相关资源
最近更新 更多