Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memoization of promise-based function

How can I memoize a promise-based function?

Would straightforward memoization of the function suffice?

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

Would this suffice?

var fooMemoized = memoize(foo);

Note: this question has been updated to remove the deferred anti-pattern.

like image 227
Ben Aston Avatar asked Feb 27 '15 10:02

Ben Aston


2 Answers

Yes, that will suffice. Promises are simple return values, which is their great benefit - in contrast to callbacks, where memoisation code would be horrible.

You only might want to make sure that the memoized promise is uncancellable, if your promise library does support some kind of cancellation. Also notice that this form of memoisation remembers rejections as well, so you can't recover from errors by "trying again".

like image 53
Bergi Avatar answered Nov 16 '22 02:11

Bergi


For promises simple sync memoize will not be good, because in most of cases you will not wish to memoize errors (rejected promises).

I did a simple library for common needs: https://github.com/nodeca/promise-memoize

  1. It memoize Promise-based function, except errors by default
  2. You can set expiration time for result
  3. If you need, you can remember (and set expiration time) for errors too.
  4. Data can be prefetched prior to expire, to never leave cache in cold state.

Pseudo code:

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));
like image 25
Vitaly Avatar answered Nov 16 '22 03:11

Vitaly