ModelBaseClass: promise mode for notifyObserversOf
Support both promise and callback styles in ModelBaseClass.notifyObserversOf. When there is no callback supplied, the method returns a promise that is resolved (or rejected) with the result.
This commit is contained in:
parent
a2836fbb56
commit
76ebdcb91b
|
@ -561,6 +561,8 @@ ModelBaseClass.observe = function(operation, listener) {
|
||||||
ModelBaseClass.notifyObserversOf = function(operation, context, callback) {
|
ModelBaseClass.notifyObserversOf = function(operation, context, callback) {
|
||||||
var observers = this._observers && this._observers[operation];
|
var observers = this._observers && this._observers[operation];
|
||||||
|
|
||||||
|
if (!callback) callback = utils.createPromiseCallback();
|
||||||
|
|
||||||
this._notifyBaseObservers(operation, context, function doNotify(err) {
|
this._notifyBaseObservers(operation, context, function doNotify(err) {
|
||||||
if (err) return callback(err, context);
|
if (err) return callback(err, context);
|
||||||
if (!observers || !observers.length) return callback(null, context);
|
if (!observers || !observers.length) return callback(null, context);
|
||||||
|
@ -579,6 +581,7 @@ ModelBaseClass.notifyObserversOf = function(operation, context, callback) {
|
||||||
function(err) { callback(err, context) }
|
function(err) { callback(err, context) }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
return callback.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelBaseClass._notifyBaseObservers = function(operation, context, callback) {
|
ModelBaseClass._notifyBaseObservers = function(operation, context, callback) {
|
||||||
|
|
28
lib/utils.js
28
lib/utils.js
|
@ -9,6 +9,7 @@ exports.defineCachedRelations = defineCachedRelations;
|
||||||
exports.sortObjectsByIds = sortObjectsByIds;
|
exports.sortObjectsByIds = sortObjectsByIds;
|
||||||
exports.setScopeValuesFromWhere = setScopeValuesFromWhere;
|
exports.setScopeValuesFromWhere = setScopeValuesFromWhere;
|
||||||
exports.mergeQuery = mergeQuery;
|
exports.mergeQuery = mergeQuery;
|
||||||
|
exports.createPromiseCallback = createPromiseCallback
|
||||||
|
|
||||||
var traverse = require('traverse');
|
var traverse = require('traverse');
|
||||||
|
|
||||||
|
@ -340,3 +341,30 @@ function sortObjectsByIds(idName, ids, objects, strict) {
|
||||||
|
|
||||||
return heading.concat(tailing);
|
return heading.concat(tailing);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createPromiseCallback() {
|
||||||
|
var cb;
|
||||||
|
|
||||||
|
if (!global.Promise) {
|
||||||
|
cb = function(){};
|
||||||
|
cb.promise = {};
|
||||||
|
Object.defineProperty(cb.promise, 'then', { get: throwPromiseNotDefined });
|
||||||
|
Object.defineProperty(cb.promise, 'catch', { get: throwPromiseNotDefined });
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
var promise = new Promise(function (resolve, reject) {
|
||||||
|
cb = function (err, data) {
|
||||||
|
if (err) return reject(err);
|
||||||
|
return resolve(data);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
cb.promise = promise;
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwPromiseNotDefined() {
|
||||||
|
throw new Error(
|
||||||
|
'Your Node runtime does support ES6 Promises. ' +
|
||||||
|
'Set "global.Promise" to your preferred implementation of promises.');
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
var ModelBuilder = require('../').ModelBuilder;
|
var ModelBuilder = require('../').ModelBuilder;
|
||||||
var should = require('./init');
|
var should = require('./init');
|
||||||
var Promise = global.Promise || require('bluebird');
|
|
||||||
|
|
||||||
describe('async observer', function() {
|
describe('async observer', function() {
|
||||||
var TestModel;
|
var TestModel;
|
||||||
|
@ -115,6 +114,28 @@ describe('async observer', function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns a promise when no callback is provided', function() {
|
||||||
|
var context = { value: 'a-test-context' };
|
||||||
|
var p = TestModel.notifyObserversOf('event', context);
|
||||||
|
(p !== undefined).should.be.true;
|
||||||
|
return p.then(function(result) {
|
||||||
|
result.should.eql(context);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a rejected promise when no callback is provided', function() {
|
||||||
|
var testError = new Error('expected test error');
|
||||||
|
TestModel.observe('event', function(ctx, next) { next(testError); });
|
||||||
|
var p = TestModel.notifyObserversOf('event', context);
|
||||||
|
return p.then(
|
||||||
|
function(result) {
|
||||||
|
throw new Error('The promise should have been rejected.');
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
err.should.eql(testError);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function pushAndNext(array, value) {
|
function pushAndNext(array, value) {
|
||||||
|
|
|
@ -26,3 +26,7 @@ if (!('getModelBuilder' in global)) {
|
||||||
return new ModelBuilder();
|
return new ModelBuilder();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!('Promise' in global)) {
|
||||||
|
global.Promise = require('bluebird');
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue