Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
public
/
sequelize
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
不要怂,就是干,撸起袖子干!
Commit 7fd629db
authored
Apr 19, 2014
by
Mick Hansen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(promises): initial implementation with backwards compat. tests
1 parent
7b798eb0
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
404 additions
and
1 deletions
lib/promise.js
lib/sequelize.js
test/promise.test.js
lib/promise.js
0 → 100644
View file @
7fd629d
var
util
=
require
(
"util"
)
,
Promise
=
require
(
"bluebird"
)
,
EventEmitter
=
require
(
"events"
).
EventEmitter
,
proxyEventKeys
=
[
'success'
,
'error'
,
'sql'
]
,
Utils
=
require
(
'./utils'
)
var
SequelizePromise
=
function
(
resolver
)
{
var
self
=
this
;
// Copied from Bluebird, bluebird doesn't like Promise.call(this)
// mhansen wrote and is no fan of this, but sees no other way of making Promises first class while preserving SQL logging capabilities and BC.
this
.
_bitField
=
0
;
this
.
_fulfillmentHandler0
=
void
0
;
this
.
_rejectionHandler0
=
void
0
;
this
.
_promise0
=
void
0
;
this
.
_receiver0
=
void
0
;
this
.
_settledValue
=
void
0
;
this
.
_boundTo
=
void
0
;
// Intercept the resolver so we can resolve with emit's
this
.
_resolveFromResolver
(
function
(
resolve
,
reject
)
{
self
.
seqResolve
=
resolve
;
self
.
seqReject
=
reject
;
if
(
resolver
)
{
resolver
.
apply
(
this
,
arguments
);
}
}.
bind
(
this
));
};
util
.
inherits
(
SequelizePromise
,
Promise
);
SequelizePromise
.
prototype
.
on
=
function
(
evt
,
fct
)
{
if
(
evt
===
'success'
)
{
this
.
then
(
fct
);
}
else
if
(
evt
===
'error'
)
{
this
.
then
(
null
,
fct
);
}
else
{
EventEmitter
.
prototype
.
on
.
call
(
this
,
evt
,
fct
);
}
return
this
;
}
SequelizePromise
.
prototype
.
emit
=
function
(
evt
)
{
var
args
=
arguments
.
length
>
1
?
Array
.
prototype
.
slice
.
call
(
arguments
,
1
)
:
[];
if
(
evt
===
'success'
)
{
this
.
seqResolve
.
apply
(
this
,
args
);
}
else
if
(
evt
===
'error'
)
{
this
.
seqReject
.
apply
(
this
,
args
);
}
else
{
EventEmitter
.
prototype
.
emit
.
apply
(
this
,
[
evt
].
concat
(
args
));
}
return
this
;
};
/**
* Listen for success events.
*
* ```js
* promise.success(function (result) {
* //...
* });
* ```
*
* @param {function} onSuccess
* @method success
* @alias ok
* @return this
*/
SequelizePromise
.
prototype
.
success
=
SequelizePromise
.
prototype
.
ok
=
function
(
fct
)
{
this
.
then
(
fct
);
return
this
;
}
/**
* Listen for error events
*
* ```js
* promise.error(function (err) {
* //...
* });
* ```
*
* @param {function} onError
* @metohd error
* @alias fail
* @alias failure
* @return this
*/
SequelizePromise
.
prototype
.
failure
=
SequelizePromise
.
prototype
.
fail
=
SequelizePromise
.
prototype
.
error
=
function
(
fct
)
{
this
.
then
(
null
,
fct
);
return
this
;
}
/**
* Listen for both success and error events.
*
* ```js
* promise.done(function (err, result) {
* //...
* });
* ```
*
* @param {function} onDone
* @method done
* @alias complete
* @return this
*/
SequelizePromise
.
prototype
.
done
=
SequelizePromise
.
prototype
.
complete
=
function
(
fct
)
{
if
(
fct
.
length
>
2
)
{
this
.
spread
(
function
()
{
fct
.
apply
(
null
,
[
null
].
concat
(
Array
.
prototype
.
slice
.
call
(
arguments
)));
},
fct
);
}
else
{
this
.
then
(
function
()
{
fct
.
apply
(
null
,
[
null
].
concat
(
Array
.
prototype
.
slice
.
call
(
arguments
)));
},
fct
);
}
return
this
;
};
/*
* Attach a function that is called every time the function that created this emitter executes a query.
* @param {function} onSQL
* @return this
*/
SequelizePromise
.
prototype
.
sql
=
function
(
fct
)
{
this
.
on
(
'sql'
,
fct
)
return
this
;
}
/**
* Proxy every event of this promise to another one.
*
* @param {SequelizePromise} The promise that should receive the events.
* @param {Object} [options]
* @param {Array} [options.events] An array of the events to proxy. Defaults to sql, error and success
* @return this
*/
SequelizePromise
.
prototype
.
proxy
=
function
(
promise
,
options
)
{
options
=
Utils
.
_
.
extend
({
events
:
proxyEventKeys
,
skipEvents
:
[]
},
options
||
{})
options
.
events
=
Utils
.
_
.
difference
(
options
.
events
,
options
.
skipEvents
)
options
.
events
.
forEach
(
function
(
eventKey
)
{
this
.
on
(
eventKey
,
function
()
{
var
args
=
[
eventKey
].
concat
([].
slice
.
apply
(
arguments
))
promise
.
emit
.
apply
(
promise
,
args
)
})
}.
bind
(
this
))
return
this
}
module
.
exports
=
SequelizePromise
;
\ No newline at end of file
lib/sequelize.js
View file @
7fd629d
...
...
@@ -10,6 +10,7 @@ var url = require("url")
,
TransactionManager
=
require
(
'./transaction-manager'
)
,
QueryTypes
=
require
(
'./query-types'
)
,
sequelizeErrors
=
require
(
'./errors'
)
,
Promise
=
require
(
'./promise'
)
/**
* This is the main class, the entry point to sequelize. To use it, you just need to import sequelize:
...
...
test/promise.test.js
View file @
7fd629d
...
...
@@ -2,8 +2,11 @@ var chai = require('chai')
,
expect
=
chai
.
expect
,
Support
=
require
(
__dirname
+
'/support'
)
,
DataTypes
=
require
(
__dirname
+
"/../lib/data-types"
)
,
SequelizePromise
=
require
(
__dirname
+
"/../lib/promise"
)
,
Promise
=
require
(
'bluebird'
)
,
dialect
=
Support
.
getTestDialect
()
,
_
=
require
(
'lodash'
)
,
sinon
=
require
(
'sinon'
)
chai
.
config
.
includeStack
=
true
...
...
@@ -358,4 +361,232 @@ describe(Support.getTestDialectTeaser("Promise"), function () {
})
})
})
})
describe
(
'backwards compat'
,
function
()
{
it
(
'should still work with .complete() when resolving'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
resolve
(
'abc'
);
});
promise
.
complete
(
spy
);
promise
.
then
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
).
to
.
deep
.
equal
([
null
,
'abc'
]);
done
()
});
});
it
(
'should still work with .success() when resolving'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
resolve
(
'yay'
);
});
promise
.
success
(
spy
);
promise
.
then
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
).
to
.
deep
.
equal
([
'yay'
]);
done
()
});
});
it
(
'should still work with .on(\'success\') when resolving'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
resolve
(
'yoohoo'
);
});
promise
.
on
(
'success'
,
spy
);
promise
.
then
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
).
to
.
deep
.
equal
([
'yoohoo'
]);
done
()
});
});
it
(
'should still work with .done() when resolving multiple results'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
resolve
(
Promise
.
all
([
'MyModel'
,
true
]));
});
promise
.
spread
(
spy
);
promise
.
done
(
function
(
err
,
model
,
created
)
{
expect
(
model
).
to
.
equal
(
'MyModel'
)
expect
(
created
).
to
.
be
.
true
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
).
to
.
deep
.
equal
([
'MyModel'
,
true
]);
done
()
});
});
it
(
'should still work with .success() when emitting'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
// no-op
});
promise
.
success
(
spy
);
promise
.
then
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
).
to
.
deep
.
equal
([
'yay'
]);
done
()
});
promise
.
emit
(
'success'
,
'yay'
);
});
it
.
only
(
'should still work with .done() when rejecting'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
reject
(
new
Error
(
'no'
));
});
promise
.
done
(
spy
);
promise
.
catch
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
[
0
]).
to
.
be
.
an
.
instanceof
(
Error
)
done
()
});
});
it
(
'should still work with .error() when throwing'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
throw
new
Error
(
'no'
);
});
promise
.
error
(
spy
);
promise
.
catch
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
[
0
]).
to
.
be
.
an
.
instanceof
(
Error
)
done
()
});
});
it
(
'should still work with .on(\'error\') when throwing'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
throw
new
Error
(
'noway'
);
});
promise
.
on
(
'error'
,
spy
);
promise
.
catch
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
[
0
]).
to
.
be
.
an
.
instanceof
(
Error
)
done
()
});
});
it
(
'should still work with .error() when emitting'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
// no-op
});
promise
.
on
(
'error'
,
spy
);
promise
.
catch
(
function
()
{
expect
(
spy
.
calledOnce
).
to
.
be
.
true
expect
(
spy
.
firstCall
.
args
[
0
]).
to
.
be
.
an
.
instanceof
(
Error
)
done
()
});
promise
.
emit
(
'error'
,
new
Error
(
'noway'
));
});
it
(
'should still support sql events'
,
function
(
done
)
{
var
spy
=
sinon
.
spy
()
,
promise
=
new
SequelizePromise
(
function
(
resolve
,
reject
)
{
resolve
(
'yay'
);
});
promise
.
on
(
'sql'
,
spy
);
promise
.
emit
(
'sql'
,
'SQL STATEMENT 1'
);
promise
.
emit
(
'sql'
,
'SQL STATEMENT 2'
);
promise
.
then
(
function
()
{
expect
(
spy
.
calledTwice
).
to
.
be
.
true
;
done
();
});
});
describe
(
"proxy"
,
function
()
{
it
(
"should correctly work with success listeners"
,
function
(
done
)
{
var
emitter
=
new
SequelizePromise
()
,
proxy
=
new
SequelizePromise
()
,
success
=
sinon
.
spy
()
emitter
.
success
(
success
)
proxy
.
success
(
function
()
{
process
.
nextTick
(
function
()
{
expect
(
success
.
called
).
to
.
be
.
true
done
()
})
})
proxy
.
proxy
(
emitter
)
proxy
.
emit
(
'success'
)
})
it
(
"should correctly work with error listeners"
,
function
(
done
)
{
var
emitter
=
new
SequelizePromise
()
,
proxy
=
new
SequelizePromise
()
,
error
=
sinon
.
spy
()
emitter
.
error
(
error
)
proxy
.
error
(
function
()
{
process
.
nextTick
(
function
()
{
expect
(
error
.
called
).
to
.
be
.
true
expect
(
error
.
firstCall
.
args
[
0
]).
to
.
be
.
an
.
instanceof
(
Error
)
done
()
})
})
proxy
.
proxy
(
emitter
)
proxy
.
emit
(
'error'
,
new
Error
(
'reason'
))
})
it
(
"should correctly work with complete/done listeners"
,
function
(
done
)
{
var
promise
=
new
SequelizePromise
()
,
proxy
=
new
SequelizePromise
()
,
complete
=
sinon
.
spy
()
promise
.
complete
(
complete
)
proxy
.
complete
(
function
()
{
process
.
nextTick
(
function
()
{
expect
(
complete
.
called
).
to
.
be
.
true
done
()
})
})
proxy
.
proxy
(
promise
)
proxy
.
emit
(
'success'
)
})
})
describe
(
"when emitting an error event with an array of errors"
,
function
()
{
describe
(
"if an error handler is given"
,
function
()
{
it
(
"should return the whole array"
,
function
(
done
)
{
var
emitter
=
new
SequelizePromise
()
var
errors
=
[
[
new
Error
(
"First error"
),
new
Error
(
"Second error"
)
],
[
new
Error
(
"Third error"
)
]
]
emitter
.
error
(
function
(
err
)
{
expect
(
err
).
to
.
equal
(
errors
)
done
()
})
emitter
.
emit
(
"error"
,
errors
)
})
})
})
});
});
\ No newline at end of file
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment