|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- 'use strict'
-
- var slice = [].slice
-
- module.exports = wrap
-
- // Wrap `fn`.
- // Can be sync or async; return a promise, receive a completion handler, return
- // new values and errors.
- function wrap(fn, callback) {
- var invoked
-
- return wrapped
-
- function wrapped() {
- var params = slice.call(arguments, 0)
- var callback = fn.length > params.length
- var result
-
- if (callback) {
- params.push(done)
- }
-
- try {
- result = fn.apply(null, params)
- } catch (error) {
- // Well, this is quite the pickle.
- // `fn` received a callback and invoked it (thus continuing the pipeline),
- // but later also threw an error.
- // We’re not about to restart the pipeline again, so the only thing left
- // to do is to throw the thing instead.
- if (callback && invoked) {
- throw error
- }
-
- return done(error)
- }
-
- if (!callback) {
- if (result && typeof result.then === 'function') {
- result.then(then, done)
- } else if (result instanceof Error) {
- done(result)
- } else {
- then(result)
- }
- }
- }
-
- // Invoke `next`, only once.
- function done() {
- if (!invoked) {
- invoked = true
-
- callback.apply(null, arguments)
- }
- }
-
- // Invoke `done` with one value.
- // Tracks if an error is passed, too.
- function then(value) {
- done(null, value)
- }
- }
|