不要怂,就是干,撸起袖子干!

Commit 698f5ae6 by Mick Hansen

feat(promises): transfer sql across .then() calls

1 parent 2f4d0f13
...@@ -653,11 +653,10 @@ module.exports = (function() { ...@@ -653,11 +653,10 @@ module.exports = (function() {
options = options || {} options = options || {}
options.force = options.force === undefined ? false : Boolean(options.force) options.force = options.force === undefined ? false : Boolean(options.force)
var self = this var self = this
, promise
// This semi awkward syntax where we can't return the chain directly but have to return the last .then() call is to allow sql proxying // This semi awkward syntax where we can't return the chain directly but have to return the last .then() call is to allow sql proxying
promise = self.Model.runHooks(self.Model.options.hooks.beforeDestroy, self).then(function () { return self.Model.runHooks(self.Model.options.hooks.beforeDestroy, self).then(function () {
var query var query
, identifier , identifier
...@@ -668,15 +667,12 @@ module.exports = (function() { ...@@ -668,15 +667,12 @@ module.exports = (function() {
identifier = self.__options.hasPrimaryKeys ? self.primaryKeyValues : { id: self.id }; identifier = self.__options.hasPrimaryKeys ? self.primaryKeyValues : { id: self.id };
query = self.QueryInterface.delete(self, self.QueryInterface.QueryGenerator.addSchema(self.Model), identifier, options) query = self.QueryInterface.delete(self, self.QueryInterface.QueryGenerator.addSchema(self.Model), identifier, options)
} }
return query
return query.proxySql(promise);
}).then(function (results) { }).then(function (results) {
return self.Model.runHooks(self.Model.options.hooks.afterDestroy, self).then(function () { return self.Model.runHooks(self.Model.options.hooks.afterDestroy, self).then(function () {
return results; return results;
}); });
}); });
return promise
} }
/** /**
......
...@@ -28,12 +28,15 @@ var SequelizePromise = function(resolver) { ...@@ -28,12 +28,15 @@ var SequelizePromise = function(resolver) {
resolver.apply(this, arguments); resolver.apply(this, arguments);
} }
}.bind(this)); }.bind(this));
// Sequelize speific
this.$sql = [];
}; };
util.inherits(SequelizePromise, Promise) util.inherits(SequelizePromise, Promise)
// Need to hack _then to make sure our promise is chainable // Need to hack _then to make sure our promise is chainable
Promise.prototype._then = function ( SequelizePromise.prototype._then = function (
didFulfill, didFulfill,
didReject, didReject,
didProgress, didProgress,
...@@ -47,6 +50,17 @@ Promise.prototype._then = function ( ...@@ -47,6 +50,17 @@ Promise.prototype._then = function (
ret._setBoundTo(this._boundTo); ret._setBoundTo(this._boundTo);
} }
/*
* Start of sequelize specific
* Needed to transfer sql events accross .then() calls
*/
if (this.proxySql && ret.emit) {
this.proxySql(ret);
}
/*
* End of sequelize specific
*/
var callbackIndex = this._addCallbacks(didFulfill, didReject, didProgress, ret, receiver); var callbackIndex = this._addCallbacks(didFulfill, didReject, didProgress, ret, receiver);
if (!haveInternalData && this._cancellable()) { if (!haveInternalData && this._cancellable()) {
...@@ -61,6 +75,20 @@ Promise.prototype._then = function ( ...@@ -61,6 +75,20 @@ Promise.prototype._then = function (
return ret; return ret;
}; };
SequelizePromise.prototype._settlePromiseAt = function (index) {
var receiver = this._receiverAt(index);
if (this.$sql && receiver && receiver.emit) {
this.$sql.forEach(function (sql) {
if (receiver && receiver.emit) {
receiver.emit('sql', sql);
}
});
}
return Promise.prototype._settlePromiseAt.apply(this, arguments);
};
SequelizePromise.prototype.on = function(evt, fct) { SequelizePromise.prototype.on = function(evt, fct) {
if (evt === 'success') { if (evt === 'success') {
this.then(fct); this.then(fct);
...@@ -83,6 +111,11 @@ SequelizePromise.prototype.emit = function(evt) { ...@@ -83,6 +111,11 @@ SequelizePromise.prototype.emit = function(evt) {
} else if (evt === 'error') { } else if (evt === 'error') {
this.seqReject.apply(this, args); this.seqReject.apply(this, args);
} else { } else {
// Needed to transfer sql across .then() calls
if (evt === 'sql') {
this.$sql.push(args[0]);
}
EventEmitter.prototype.emit.apply(this, [evt].concat(args)); EventEmitter.prototype.emit.apply(this, [evt].concat(args));
} }
......
...@@ -2,6 +2,7 @@ var Utils = require(__dirname + '/utils') ...@@ -2,6 +2,7 @@ var Utils = require(__dirname + '/utils')
, DataTypes = require(__dirname + '/data-types') , DataTypes = require(__dirname + '/data-types')
, SQLiteQueryInterface = require(__dirname + '/dialects/sqlite/query-interface') , SQLiteQueryInterface = require(__dirname + '/dialects/sqlite/query-interface')
, Transaction = require(__dirname + '/transaction') , Transaction = require(__dirname + '/transaction')
, Promise = require(__dirname + '/promise')
, QueryTypes = require('./query-types') , QueryTypes = require('./query-types')
module.exports = (function() { module.exports = (function() {
...@@ -532,73 +533,74 @@ module.exports = (function() { ...@@ -532,73 +533,74 @@ module.exports = (function() {
} }
} }
return new Utils.CustomEventEmitter(function(emitter) { var emitter = new Promise();
var tick = 0 var tick = 0
var iterate = function(err, i) { var iterate = function(err, i) {
if (!!err || i >= cascades.length) { if (!!err || i >= cascades.length) {
return run(err) return run(err)
}
dao[cascades[i]]().success(function(tasks) {
if (tasks === null || tasks.length < 1) {
return run()
} }
dao[cascades[i]]().success(function(tasks) { tasks = Array.isArray(tasks) ? tasks : [tasks]
if (tasks === null || tasks.length < 1) {
return run() var ii = 0
var next = function(err, ii) {
if (!!err || ii >= tasks.length) {
return iterate(err)
} }
tasks = Array.isArray(tasks) ? tasks : [tasks] tasks[ii].destroy().error(function(err) {
return iterate(err)
})
.success(function() {
ii++
var ii = 0 if (ii >= tasks.length) {
var next = function(err, ii) { tick++
if (!!err || ii >= tasks.length) { return iterate(null, tick)
return iterate(err)
} }
tasks[ii].destroy().error(function(err) { next(null, ii)
return iterate(err) })
}) }
.success(function() {
ii++
if (ii >= tasks.length) {
tick++
return iterate(null, tick)
}
next(null, ii) next(null, ii)
}) })
} }
next(null, ii) var run = function(err) {
}) if (!!err) {
return emitter.emit('error', err)
} }
var run = function(err) { var chainer = new Utils.QueryChainer()
if (!!err) {
return emitter.emit('error', err)
}
var chainer = new Utils.QueryChainer()
chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete']) chainer.add(self, 'queryAndEmit', [[sql, dao, options], 'delete'])
chainer.runSerially() chainer.runSerially()
.success(function(results){ .success(function(results){
emitter.query = { sql: sql } emitter.query = { sql: sql }
emitter.emit('sql', sql) emitter.emit('sql', sql)
emitter.emit('success', results[1]) emitter.emit('success', results[1])
}) })
.error(function(err) { .error(function(err) {
emitter.query = { sql: sql } emitter.query = { sql: sql }
emitter.emit('sql', sql) emitter.emit('sql', sql)
emitter.emit('error', err) emitter.emit('error', err)
}) })
} }
if (cascades.length > 0) { if (cascades.length > 0) {
iterate(null, tick) iterate(null, tick)
} else { } else {
run() run()
} }
}).run()
return emitter;
} }
QueryInterface.prototype.bulkDelete = function(tableName, identifier, options) { QueryInterface.prototype.bulkDelete = function(tableName, identifier, options) {
...@@ -865,7 +867,6 @@ module.exports = (function() { ...@@ -865,7 +867,6 @@ module.exports = (function() {
}, options || {}) }, options || {})
var execQuery = function(emitter) { var execQuery = function(emitter) {
if (Array.isArray(sqlOrQueryParams)) { if (Array.isArray(sqlOrQueryParams)) {
if (sqlOrQueryParams.length === 1) { if (sqlOrQueryParams.length === 1) {
sqlOrQueryParams.push(null) sqlOrQueryParams.push(null)
...@@ -897,12 +898,14 @@ module.exports = (function() { ...@@ -897,12 +898,14 @@ module.exports = (function() {
emitter.emit('error', err) emitter.emit('error', err)
}.bind(this)) }.bind(this))
.proxy(emitter, { events: ['sql'] }) .proxy(emitter, { events: ['sql'] })
return emitter;
}.bind(this) }.bind(this)
if (!!emitter) { if (!!emitter) {
execQuery(emitter) execQuery(emitter)
} else { } else {
return new Utils.CustomEventEmitter(execQuery).run() return execQuery(new Promise());
} }
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!