You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.3 KiB
64 lines
1.3 KiB
'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) |
|
} |
|
}
|
|
|