From e3cf75c10dc391f49f25b8da2306748778d457fd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Oct 2015 13:02:48 +0200 Subject: [PATCH 01/12] added file system store engine to README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 611b3ec..92553a0 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ See the [Express.js cache-manager example app](https://github.com/BryanDonovan/n * [node-cache-manager-mongodb](https://github.com/v4l3r10/node-cache-manager-mongodb) +* [node-cache-manager-fs](https://github.com/hotelde/node-cache-manager-fs) + ## Overview First, it includes a `wrap` function that lets you wrap any function in cache. From a29be318f3801bd5f9ea6e72b5a13d4a9f5e52d8 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 18 Jan 2016 11:25:00 +0100 Subject: [PATCH 02/12] Add Promise support when using cache.wrap --- .jshintrc | 1 + lib/caching.js | 18 ++++++++++++++ lib/callback_filler.js | 6 +++++ test/caching.unit.js | 56 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/.jshintrc b/.jshintrc index d2de774..7ab039b 100644 --- a/.jshintrc +++ b/.jshintrc @@ -20,6 +20,7 @@ "predef" : [ // Extra globals. "__dirname", + "Promise", "Buffer", "event", "exports", diff --git a/lib/caching.js b/lib/caching.js index f98bb3a..225386a 100644 --- a/lib/caching.js +++ b/lib/caching.js @@ -69,6 +69,17 @@ var caching = function(args) { options = {}; } + if (!cb) { + cb = Promise.defer(); + var work2 = work; + work = function(cb) { + Promise.resolve().then(work2).then(function(res) { + cb(null, res); + }) + .catch(cb); + }; + } + var hasKey = callbackFiller.has(key); callbackFiller.add(key, {cb: cb, domain: process.domain}); if (hasKey) { return; } @@ -91,6 +102,9 @@ var caching = function(args) { } if (!self._isCacheableValue(data)) { + if (typeof cb === 'object') { + return cb.resolve(data); + } return cb(); } @@ -104,6 +118,10 @@ var caching = function(args) { }); } }); + + if (typeof cb === 'object') { + return cb.promise; + } }; /** diff --git a/lib/callback_filler.js b/lib/callback_filler.js index 4914bf1..5f73f67 100644 --- a/lib/callback_filler.js +++ b/lib/callback_filler.js @@ -12,6 +12,12 @@ CallbackFiller.prototype.fill = function(key, err, data) { waiting.forEach(function(task) { var taskDomain = task.domain || domain.create(); + if (typeof task.cb === 'object') { + if (err) { + return taskDomain.bind(task.cb.reject)(err); + } + return taskDomain.bind(task.cb.resolve)(data); + } taskDomain.bind(task.cb)(err, data); }); }; diff --git a/test/caching.unit.js b/test/caching.unit.js index 227e4f9..c43ce7a 100644 --- a/test/caching.unit.js +++ b/test/caching.unit.js @@ -673,6 +673,62 @@ describe("caching", function() { }); }); }); + + describe("using native promises", function() { + beforeEach(function() { + cache = caching({ + store: 'memory', + max: 50, + ttl: 5 * 60 + }); + }); + + it("should be able to chain with simple promise", function(done) { + cache.wrap('key', function() { + return 'OK'; + }) + .then(function(res) { + assert.equal(res, 'OK'); + done(); + }); + }); + + it("should be able to chain with cache function as a promise", function(done) { + cache.wrap('key', function() { + return new Promise(function(resolve) { + resolve('OK'); + }); + }) + .then(function(res) { + assert.equal(res, 'OK'); + done(); + }); + }); + + it("should be able to catch errors in cache function as a promise", function(done) { + cache.wrap('key', function() { + return new Promise(function(resolve, reject) { + reject('NOK'); + }); + }) + .then(function() { + done(new Error('It should not call then since there is an error in the cache function!')); + }) + .catch(function() { + done(); + }); + }); + + it("should be able to chain with non-cacheable value", function(done) { + cache.wrap('key', function() { + return; + }) + .then(function(res) { + assert.equal(res, undefined); + done(); + }); + }); + }); }); describe("instantiating with no store passed in", function() { From b92743fb871ce64e5b8673f0447121b76d62b424 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 18 Jan 2016 11:33:34 +0100 Subject: [PATCH 03/12] Add multi-caching promise support for Wrap --- lib/multi_caching.js | 18 +++++++++++ test/multi_caching.unit.js | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index 5b4a90b..73fe35f 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -145,6 +145,17 @@ var multiCaching = function(caches, options) { }; } + if (!cb) { + cb = Promise.defer(); + var work2 = work; + work = function(cb) { + Promise.resolve().then(work2).then(function(res) { + cb(null, res); + }) + .catch(cb); + }; + } + var hasKey = callbackFiller.has(key); callbackFiller.add(key, {cb: cb, domain: process.domain}); if (hasKey) { return; } @@ -175,6 +186,9 @@ var multiCaching = function(caches, options) { } if (!self._isCacheableValue(data)) { + if (typeof cb === 'object') { + return cb.resolve(data); + } return cb(); } @@ -186,6 +200,10 @@ var multiCaching = function(caches, options) { }); } }); + + if (typeof cb === 'object') { + return cb.promise; + } }; /** diff --git a/test/multi_caching.unit.js b/test/multi_caching.unit.js index 4b81b0c..09da385 100644 --- a/test/multi_caching.unit.js +++ b/test/multi_caching.unit.js @@ -970,6 +970,70 @@ describe("multiCaching", function() { }); }); }); + + describe("using native promises", function() { + beforeEach(function() { + multiCache = multiCaching([memoryCache, memoryCache3]); + }); + + it("should be able to chain with simple promise", function(done) { + multiCache.wrap('key', function() { + return 'OK'; + }) + .then(function(res) { + assert.equal(res, 'OK'); + done(); + }); + }); + + it("should be able to chain with cache function as a promise", function(done) { + multiCache.wrap('key', function() { + return new Promise(function(resolve) { + resolve('OK'); + }); + }) + .then(function(res) { + assert.equal(res, 'OK'); + done(); + }); + }); + + it("should be able to catch errors in cache function as a promise", function(done) { + multiCache.wrap('key', function() { + return new Promise(function(resolve, reject) { + reject('NOK'); + }); + }) + .then(function() { + done(new Error('It should not call then since there is an error in the cache function!')); + }) + .catch(function() { + done(); + }); + }); + + it("should be able to catch a throw in cache function as a promise", function(done) { + multiCache.wrap('key', function() { + throw 'NOK'; + }) + .then(function() { + done(new Error('It should not call then since there is an error in the cache function!')); + }) + .catch(function() { + done(); + }); + }); + + it("should be able to chain with non-cacheable value", function(done) { + multiCache.wrap('key', function() { + return; + }) + .then(function(res) { + assert.equal(res, undefined); + done(); + }); + }); + }); }); context("when instantiated with a non-Array 'caches' arg", function() { From c3699a61e6bd03d7a8a46130d834270a20c50fd3 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 18 Jan 2016 11:33:51 +0100 Subject: [PATCH 04/12] Remove unused statement (unable to pass through) --- lib/multi_caching.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index 73fe35f..88c235d 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -176,8 +176,6 @@ var multiCaching = function(caches, options) { .on('error', function(err) { if (callbackFiller.has(key)) { callbackFiller.fill(key, err); - } else { - cb(err); } }) .bind(work)(function(err, data) { From 74d4e4b2d441b23ed3b9cedf0f19035316099cb7 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 18 Jan 2016 12:00:11 +0100 Subject: [PATCH 05/12] Add promise support for get/set --- lib/multi_caching.js | 54 +++++++++++++++++++++++++++++++++----- lib/stores/memory.js | 3 +++ test/multi_caching.unit.js | 13 +++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index 88c235d..4444bf4 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -64,7 +64,11 @@ var multiCaching = function(caches, options) { if (_isCacheableValue(result)) { // break out of async loop. - return cb(err, result, i); + if (typeof cb === 'function') { + return cb(err, result, i); + } else { + return cb.resolve(result); + } } i += 1; @@ -72,7 +76,17 @@ var multiCaching = function(caches, options) { }; cache.store.get(key, options, callback); - }, cb); + }, function(err, result) { + if (typeof cb === 'object') { + if (err) { + cb.reject(err); + } else { + cb.resolve(result); + } + } else if (typeof cb === 'function') { + cb(err, result); + } + }); } function setInMultipleCaches(caches, opts, cb) { @@ -85,7 +99,17 @@ var multiCaching = function(caches, options) { } else { next(); } - }, cb); + }, function(err, result) { + if (typeof cb === 'object') { + if (err) { + cb.reject(err); + } else { + cb.resolve(result); + } + } else if (typeof cb === 'function') { + cb(err, result); + } + }); } /** @@ -98,10 +122,18 @@ var multiCaching = function(caches, options) { self.getAndPassUp = function(key, cb) { getFromHighestPriorityCache(key, function(err, result, index) { if (err) { - return cb(err); + if (typeof cb === 'function') { + return cb(err); + } else { + return cb.reject(err); + } } - cb(err, result); + if (typeof cb === 'function') { + cb(err, result); + } else { + cb.resolve(result); + } if (index) { var cachesToUpdate = caches.slice(0, index); @@ -227,7 +259,11 @@ var multiCaching = function(caches, options) { options: options }; - setInMultipleCaches(caches, opts, cb); + var defer = Promise.defer(); + + setInMultipleCaches(caches, opts, cb || defer); + + return defer.promise; }; /** @@ -246,7 +282,11 @@ var multiCaching = function(caches, options) { options = {}; } - getFromHighestPriorityCache(key, options, cb); + var defer = Promise.defer(); + + getFromHighestPriorityCache(key, options, cb || defer); + + return defer.promise; }; /** diff --git a/lib/stores/memory.js b/lib/stores/memory.js index 0d6d4f9..7480382 100644 --- a/lib/stores/memory.js +++ b/lib/stores/memory.js @@ -27,6 +27,8 @@ var memoryStore = function(args) { lruCache.set(key, value, maxAge); if (cb) { process.nextTick(cb); + } else { + return Promise.resolve(value); } }; @@ -35,6 +37,7 @@ var memoryStore = function(args) { cb = options; } var value = lruCache.get(key); + if (cb) { process.nextTick(function() { cb(null, value); diff --git a/test/multi_caching.unit.js b/test/multi_caching.unit.js index 09da385..c50247e 100644 --- a/test/multi_caching.unit.js +++ b/test/multi_caching.unit.js @@ -181,6 +181,19 @@ describe("multiCaching", function() { }); }); }); + + describe('using promises', function() { + it('should return a promise and resolve it', function(done) { + memoryCache3.set(key, value) + .then(function() { + return multiCache.get(key); + }) + .then(function(result) { + assert.equal(result, value); + }) + .then(done); + }); + }); }); describe("del()", function() { From 9c2ae65bc4e4a4350cb51532ec6cb1e2eaed1f4a Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 18 Jan 2016 12:59:27 +0100 Subject: [PATCH 06/12] More coverage + refactor promise usage on multi cache getters --- lib/multi_caching.js | 36 +++++++++++++++--------------------- test/multi_caching.unit.js | 28 +++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index 4444bf4..dd552a4 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -53,6 +53,8 @@ var multiCaching = function(caches, options) { options = {}; } + var defer = Promise.defer(); + var i = 0; async.eachSeries(caches, function(cache, next) { var callback = function(err, result) { @@ -66,9 +68,8 @@ var multiCaching = function(caches, options) { // break out of async loop. if (typeof cb === 'function') { return cb(err, result, i); - } else { - return cb.resolve(result); } + return defer.resolve(result); } i += 1; @@ -77,16 +78,17 @@ var multiCaching = function(caches, options) { cache.store.get(key, options, callback); }, function(err, result) { - if (typeof cb === 'object') { - if (err) { - cb.reject(err); - } else { - cb.resolve(result); - } - } else if (typeof cb === 'function') { + if (typeof cb === 'function') { cb(err, result); } + + if (err) { + return defer.reject(err); + } + defer.resolve(result); }); + + return defer.promise; } function setInMultipleCaches(caches, opts, cb) { @@ -120,19 +122,15 @@ var multiCaching = function(caches, options) { * @param {function} cb */ self.getAndPassUp = function(key, cb) { - getFromHighestPriorityCache(key, function(err, result, index) { + return getFromHighestPriorityCache(key, function(err, result, index) { if (err) { - if (typeof cb === 'function') { + if (cb) { return cb(err); - } else { - return cb.reject(err); } } - if (typeof cb === 'function') { + if (cb) { cb(err, result); - } else { - cb.resolve(result); } if (index) { @@ -282,11 +280,7 @@ var multiCaching = function(caches, options) { options = {}; } - var defer = Promise.defer(); - - getFromHighestPriorityCache(key, options, cb || defer); - - return defer.promise; + return getFromHighestPriorityCache(key, options, cb); }; /** diff --git a/test/multi_caching.unit.js b/test/multi_caching.unit.js index c50247e..955e623 100644 --- a/test/multi_caching.unit.js +++ b/test/multi_caching.unit.js @@ -183,7 +183,7 @@ describe("multiCaching", function() { }); describe('using promises', function() { - it('should return a promise and resolve it', function(done) { + it('gets data from first cache that has it', function(done) { memoryCache3.set(key, value) .then(function() { return multiCache.get(key); @@ -193,6 +193,23 @@ describe("multiCaching", function() { }) .then(done); }); + + it("passes any options to underlying caches", function(done) { + var opts = {foo: 'bar'}; + + multiCache.set(key, value) + .then(function() { + sinon.spy(memoryCache.store, 'get'); + return multiCache.get(key, opts); + }) + .then(function(result) { + assert.equal(result, value); + assert.ok(memoryCache.store.get.calledWith(key, opts)); + + memoryCache.store.get.restore(); + }) + .then(done); + }); }); }); @@ -360,6 +377,15 @@ describe("multiCaching", function() { done(); }); }); + + it("bubbles up errors from caches and reject promise", function(done) { + multiCache.getAndPassUp(key) + .catch(function(err) { + assert.ok(memoryStoreStub.get.called); + assert.equal(err, fakeError); + done(); + }); + }); }); }); }); From 5dae350582169df0e33b8031e43d4347813cc397 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 20 Jan 2016 00:09:43 +0100 Subject: [PATCH 07/12] Refactor promise usage and return it only if no callback provided --- lib/multi_caching.js | 50 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index dd552a4..eac6c91 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -53,7 +53,11 @@ var multiCaching = function(caches, options) { options = {}; } - var defer = Promise.defer(); + var promised = false; + if (!cb) { + cb = Promise.defer(); + promised = true; + } var i = 0; async.eachSeries(caches, function(cache, next) { @@ -66,10 +70,10 @@ var multiCaching = function(caches, options) { if (_isCacheableValue(result)) { // break out of async loop. - if (typeof cb === 'function') { + if (!promised) { return cb(err, result, i); } - return defer.resolve(result); + return cb.resolve(result); } i += 1; @@ -78,21 +82,27 @@ var multiCaching = function(caches, options) { cache.store.get(key, options, callback); }, function(err, result) { - if (typeof cb === 'function') { - cb(err, result); + if (!promised) { + return cb(err, result); } - if (err) { - return defer.reject(err); - } - defer.resolve(result); + return (err) ? cb.reject(err) : cb.resolve(result); }); - return defer.promise; + if (promised) { + return cb.promise; + } } function setInMultipleCaches(caches, opts, cb) { opts.options = opts.options || {}; + + var promised = false; + if (!cb) { + promised = true; + cb = Promise.defer(); + } + async.each(caches, function(cache, next) { var _isCacheableValue = getIsCacheableValueFunction(cache); @@ -102,16 +112,16 @@ var multiCaching = function(caches, options) { next(); } }, function(err, result) { - if (typeof cb === 'object') { - if (err) { - cb.reject(err); - } else { - cb.resolve(result); - } - } else if (typeof cb === 'function') { + if (promised) { + return (err) ? cb.reject(err) : cb.resolve(result); + } else { cb(err, result); } }); + + if (promised) { + return cb.promise; + } } /** @@ -257,11 +267,7 @@ var multiCaching = function(caches, options) { options: options }; - var defer = Promise.defer(); - - setInMultipleCaches(caches, opts, cb || defer); - - return defer.promise; + return setInMultipleCaches(caches, opts, cb); }; /** From e45393a9e533bf9ed78b1abfe73c4d99b1beb672 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 20 Jan 2016 00:25:50 +0100 Subject: [PATCH 08/12] Promisify getAndPassUp --- lib/multi_caching.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/multi_caching.js b/lib/multi_caching.js index eac6c91..6506d9e 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -132,15 +132,15 @@ var multiCaching = function(caches, options) { * @param {function} cb */ self.getAndPassUp = function(key, cb) { - return getFromHighestPriorityCache(key, function(err, result, index) { - if (err) { - if (cb) { - return cb(err); - } - } + var promised = false; + if (!cb) { + promised = true; + cb = Promise.defer(); + } - if (cb) { - cb(err, result); + getFromHighestPriorityCache(key, function(err, result, index) { + if (err) { + return (!promised) ? cb(err) : cb.reject(err); } if (index) { @@ -153,7 +153,13 @@ var multiCaching = function(caches, options) { } }); } + + return (!promised) ? cb(err, result) : cb.resolve(result); }); + + if (promised) { + return cb.promise; + } }; /** From 99a71b68ef704f5fc93f0e74c1682eb8c329f5b6 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 20 Jan 2016 00:34:55 +0100 Subject: [PATCH 09/12] More coverage using promises --- test/multi_caching.unit.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/multi_caching.unit.js b/test/multi_caching.unit.js index 955e623..97da932 100644 --- a/test/multi_caching.unit.js +++ b/test/multi_caching.unit.js @@ -289,6 +289,17 @@ describe("multiCaching", function() { }); }); }); + + it("gets data from first cache that has it using promises", function(done) { + memoryCache3.set(key, value) + .then(function() { + return multiCache.getAndPassUp(key); + }) + .then(function(result) { + assert.equal(result, value); + done(); + }); + }); }); describe("when value is not found in any cache", function() { @@ -353,6 +364,22 @@ describe("multiCaching", function() { }); }); + it("checks to see if higher levels have item using promises", function(done) { + memoryCache3.set(key, value) + .then(function() { + return multiCache.getAndPassUp(key); + }) + .then(function(result) { + assert.equal(result, value); + }) + .then(function() { + process.nextTick(function() { + assert.equal(memoryCache.get(key), value); + }); + }) + .then(done); + }); + context("when a cache store calls back with an error", function() { var fakeError; var memoryStoreStub; From 40ed0bea866ff07cde088c03a60f4d249a4ae88d Mon Sep 17 00:00:00 2001 From: Jonathan Muller Date: Sun, 24 Jan 2016 12:19:18 +0100 Subject: [PATCH 10/12] Allow usage before declaration for functions only --- .jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index 7ab039b..fb5dc81 100644 --- a/.jshintrc +++ b/.jshintrc @@ -59,7 +59,7 @@ "expr" : false, // Tolerate `ExpressionStatement` as Programs. "forin" : false, // Tolerate `for in` loops without `hasOwnProperty`. "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` - "latedef" : true, // Prohibit variable use before definition. + "latedef" : "nofunc", // Prohibit variable use before definition. "loopfunc" : true, // Allow functions to be defined within loops. "maxparams" : 4, "maxdepth" : 5, From a4e2eb57252090857395d59e5eb44674b8501c6f Mon Sep 17 00:00:00 2001 From: Jonathan Muller Date: Sun, 24 Jan 2016 12:19:56 +0100 Subject: [PATCH 11/12] Refactor the whole promise thing --- lib/caching.js | 34 +++++++------ lib/callback_filler.js | 6 --- lib/multi_caching.js | 108 ++++++++++++++++++++++------------------- 3 files changed, 77 insertions(+), 71 deletions(-) diff --git a/lib/caching.js b/lib/caching.js index 225386a..b162837 100644 --- a/lib/caching.js +++ b/lib/caching.js @@ -42,6 +42,24 @@ var caching = function(args) { }; } + function wrapPromise(key, promise, options) { + return new Promise(function(resolve, reject) { + self.wrap(key, function(cb) { + Promise.resolve() + .then(promise) + .then(function(result) { + cb(null, result); + }) + .catch(cb); + }, options, function(err, result) { + if (err) { + return reject(err); + } + resolve(result); + }); + }); + } + /** * Wraps a function in cache. I.e., the first time the function is run, * its results are stored in cache so subsequent calls retrieve from cache @@ -70,14 +88,7 @@ var caching = function(args) { } if (!cb) { - cb = Promise.defer(); - var work2 = work; - work = function(cb) { - Promise.resolve().then(work2).then(function(res) { - cb(null, res); - }) - .catch(cb); - }; + return wrapPromise(key, work, options); } var hasKey = callbackFiller.has(key); @@ -102,9 +113,6 @@ var caching = function(args) { } if (!self._isCacheableValue(data)) { - if (typeof cb === 'object') { - return cb.resolve(data); - } return cb(); } @@ -118,10 +126,6 @@ var caching = function(args) { }); } }); - - if (typeof cb === 'object') { - return cb.promise; - } }; /** diff --git a/lib/callback_filler.js b/lib/callback_filler.js index 5f73f67..4914bf1 100644 --- a/lib/callback_filler.js +++ b/lib/callback_filler.js @@ -12,12 +12,6 @@ CallbackFiller.prototype.fill = function(key, err, data) { waiting.forEach(function(task) { var taskDomain = task.domain || domain.create(); - if (typeof task.cb === 'object') { - if (err) { - return taskDomain.bind(task.cb.reject)(err); - } - return taskDomain.bind(task.cb.resolve)(data); - } taskDomain.bind(task.cb)(err, data); }); }; diff --git a/lib/multi_caching.js b/lib/multi_caching.js index 6506d9e..15dcfe0 100644 --- a/lib/multi_caching.js +++ b/lib/multi_caching.js @@ -47,16 +47,25 @@ var multiCaching = function(caches, options) { } } + function getFromHighestPriorityCachePromise(key, options) { + return new Promise(function(resolve, reject) { + getFromHighestPriorityCache(key, options, function(err, result) { + if (err) { + return reject(err); + } + resolve(result); + }); + }); + } + function getFromHighestPriorityCache(key, options, cb) { if (typeof options === 'function') { cb = options; options = {}; } - var promised = false; if (!cb) { - cb = Promise.defer(); - promised = true; + return getFromHighestPriorityCachePromise(key, options); } var i = 0; @@ -70,10 +79,7 @@ var multiCaching = function(caches, options) { if (_isCacheableValue(result)) { // break out of async loop. - if (!promised) { - return cb(err, result, i); - } - return cb.resolve(result); + return cb(err, result, i); } i += 1; @@ -82,25 +88,26 @@ var multiCaching = function(caches, options) { cache.store.get(key, options, callback); }, function(err, result) { - if (!promised) { - return cb(err, result); - } - - return (err) ? cb.reject(err) : cb.resolve(result); + return cb(err, result); }); + } - if (promised) { - return cb.promise; - } + function setInMultipleCachesPromise(caches, opts) { + return new Promise(function(resolve, reject) { + setInMultipleCaches(caches, opts, function(err, result) { + if (err) { + return reject(err); + } + resolve(result); + }); + }); } function setInMultipleCaches(caches, opts, cb) { opts.options = opts.options || {}; - var promised = false; if (!cb) { - promised = true; - cb = Promise.defer(); + return setInMultipleCachesPromise(caches, opts); } async.each(caches, function(cache, next) { @@ -112,16 +119,19 @@ var multiCaching = function(caches, options) { next(); } }, function(err, result) { - if (promised) { - return (err) ? cb.reject(err) : cb.resolve(result); - } else { - cb(err, result); - } + cb(err, result); }); + } - if (promised) { - return cb.promise; - } + function getAndPassUpPromise(key) { + return new Promise(function(resolve, reject) { + self.getAndPassUp(key, function(err, result) { + if (err) { + return reject(err); + } + resolve(result); + }); + }); } /** @@ -132,15 +142,13 @@ var multiCaching = function(caches, options) { * @param {function} cb */ self.getAndPassUp = function(key, cb) { - var promised = false; if (!cb) { - promised = true; - cb = Promise.defer(); + return getAndPassUpPromise(key); } getFromHighestPriorityCache(key, function(err, result, index) { if (err) { - return (!promised) ? cb(err) : cb.reject(err); + return cb(err); } if (index) { @@ -154,14 +162,28 @@ var multiCaching = function(caches, options) { }); } - return (!promised) ? cb(err, result) : cb.resolve(result); + return cb(err, result); }); - - if (promised) { - return cb.promise; - } }; + function wrapPromise(key, promise, options) { + return new Promise(function(resolve, reject) { + self.wrap(key, function(cb) { + Promise.resolve() + .then(promise) + .then(function(result) { + cb(null, result); + }) + .catch(cb); + }, options, function(err, result) { + if (err) { + return reject(err); + } + resolve(result); + }); + }); + } + /** * Wraps a function in one or more caches. * Has same API as regular caching module. @@ -192,14 +214,7 @@ var multiCaching = function(caches, options) { } if (!cb) { - cb = Promise.defer(); - var work2 = work; - work = function(cb) { - Promise.resolve().then(work2).then(function(res) { - cb(null, res); - }) - .catch(cb); - }; + return wrapPromise(key, work, options); } var hasKey = callbackFiller.has(key); @@ -230,9 +245,6 @@ var multiCaching = function(caches, options) { } if (!self._isCacheableValue(data)) { - if (typeof cb === 'object') { - return cb.resolve(data); - } return cb(); } @@ -244,10 +256,6 @@ var multiCaching = function(caches, options) { }); } }); - - if (typeof cb === 'object') { - return cb.promise; - } }; /** From 7e2b41f681fbb25685c8459465a4852a787a8f24 Mon Sep 17 00:00:00 2001 From: Jonathan Muller Date: Sun, 24 Jan 2016 12:24:39 +0100 Subject: [PATCH 12/12] Add Polyfill for promises on test env when using node without Promise support --- package.json | 1 + test/run.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index 5e83012..8d08f92 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "devDependencies": { "coveralls": "^2.3.0", + "es6-promise": "^3.0.2", "istanbul": "^0.2.11", "jscs": "^1.9.0", "jsdoc": "^3.3.0", diff --git a/test/run.js b/test/run.js index 2bfa5c0..7aac560 100755 --- a/test/run.js +++ b/test/run.js @@ -6,6 +6,10 @@ var Mocha = require('mocha'); var optimist = require('optimist'); var walkDir = require('./support').walkDir; +if (typeof Promise === "undefined") { + global.Promise = require('es6-promise').Promise; +} + var argv = optimist .usage("Usage: $0 -t [types] --reporter [reporter] --timeout [timeout]")['default']( {types: 'unit,functional', reporter: 'spec', timeout: 6000})