繁体   English   中英

基于承诺的功能的记忆

[英]Memoization of promise-based function

如何记忆基于承诺的功能?

直截了当的功能记忆就够了吗?

function foo() {
    return new Promise((resolve, reject) => {
      doSomethingAsync({ success: resolve, fail: reject });
    });
};

这样就够了吗?

var fooMemoized = memoize(foo);

注意:此问题已更新,以删除延迟反模式。

是的,这就足够了。 Promise是简单的返回值,这是它们的巨大好处 - 与回调相比,memoisation代码会很糟糕。

如果您的承诺库确实支持某种取消,您可能只想确保备忘的承诺是无法撤销的。 另请注意,这种形式的记忆也会记住拒绝,因此您无法通过“再次尝试”来从错误中恢复。

对于promises,简单同步memoize不会很好,因为在大多数情况下你不希望记住错误(拒绝承诺)。

我为常见需求做了一个简单的库: https//github.com/nodeca/promise-memoize

  1. 它会记住基于Promise的函数,默认情况下除了错误
  2. 您可以设置结果的到期时间
  3. 如果需要,您也可以记住(并设置过期时间)错误。
  4. 数据可以在到期之前预取,从不将缓存留在冷态。

伪代码:

let db = require('mongoose').createConnection('mongodb://localhost/forum');

function lastPosts(limit) {
  return db.model('Post').find()
    .limit(limit).orderBy('-_id').lean(true).exec(); // <- Promise (thenable)
}

let cachedLastPosts = require('promise-memoize')(lastPosts, { maxAge: 60000 });

// Later...
cachedLastPosts(10).then(posts => console.log(posts));

请注意,您的函数具有延迟反模式,可以进一步简化:

foo.value = null;
function foo(){
    if(foo.value) return foo.value;
    return (foo.value = doSomethingAsync());
}

也就是说,memoization非常简单,在这种情况下你甚至不必调用.memoize 您的原始功能也会抑制错误。

正如@Bergi和@BenjaminGruenbaum指出的那样,这里的memoization很好,但应该指出你的foo函数没有任何用处,实际上是在引入bug(参见:deferred antipattern)。

如果您只想记住doSomethingAsync的结果,那么您可以删除中间人:

var fooMemoized = memoize(doSomethingAsync);

或者如果你实际上过于简单化并且foo()将参数传递给doSomethingAsync ,那么你仍然可以将它减少到一行:

function foo() {
    return doSomethingAsync(argument1, argument2, etc.);
}
var fooMemoized = memoize(foo);

或者,如果您实际上并不打算使用foo() ,则可以执行以下操作:

var fooMemoized = memoize(function () {
    return doSomethingAsync(argument1, argument2, etc.);
});

记忆和承诺并不明显。 使用新的async / await语法甚至更糟糕。

为了得到像这样的工作:

memoize(async () => 42) 

要么

const whatsTheAnswerToLifeTheUniverseAndEverything = () => 42
memoize(whatsTheAnswerToLifeTheUniverseAndEverything) 

您需要一个支持promises和异步语法的memoize函数或库。 其中几个: - https://github.com/aboutlo/async-memo-ize (披露:我做了这个lib) - https://github.com/medikoo/memoizee

注意:Memoization是一种很酷的技术,但是你会以内存消耗为代价来节省CPU资源。 你应该注意这些图书馆如何大规模地处理这个问题;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM