The source code for the Promisify prototype in BlueBird is
Promise.promisify = function (fn, options) {
if (typeoffn ! = ="function") {
throw new TypeError("expecting a function but got " + util.classString(fn));
}
if (isPromisified(fn)) {
return fn;
}
options = Object(options);
var receiver = options.context === undefined ? THIS : options.context;
varmultiArgs = !! options.multiArgs;var ret = promisify(fn, receiver, multiArgs);
util.copyDescriptors(fn, ret, propsFilter);
return ret;
};
Copy the code
You can see that while we’re determining whether fn is a function, we’re also determining whether fn has been promised. (fn,undefined); promisify (fn,{},false)
function promisify(callback, receiver, multiArgs) {
return makeNodePromisified(callback, receiver, undefined,
callback, null, multiArgs);
}
Copy the code
Promisify actually wraps the makeNodePromisified function, passing the parameter
var makeNodePromisified = canEvaluate
? makeNodePromisifiedEval
: makeNodePromisifiedClosure;
Copy the code
The makeNodePromisified function uses the canEvaluate variable, which determines whether the runtime environment is a browser or not. Here we call makeNodePromisifiedClosure this function
function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
var defaultThis = (function() {return this; }) ();var method = callback;
if (typeof method === "string") {
callback = fn;
}
function promisified() {
var _receiver = receiver;
if (receiver === THIS) _receiver = this;
var promise = new Promise(INTERNAL);
promise._captureStackTrace();
var cb = typeof method === "string" && this! == defaultThis ?this[method] : callback;
var fn = nodebackForPromise(promise, multiArgs);/ / into a promise
try {
cb.apply(_receiver, withAppended(arguments, fn));// Call the cb passed in
} catch(e) {
promise._rejectCallback(maybeWrapAsError(e), true.true);
}
if(! promise._isFateSealed()) promise._setAsyncGuaranteed();return promise;
}
util.notEnumerableProp(promisified, "__isPromisified__".true);
return promisified;
}
Copy the code
We bind _receiver to this and call nodebackForPromise to return a promise to fn. The source code for nodebackForPromise is
function nodebackForPromise(promise, multiArgs) {
return function(err, value) {
if (promise === null) return;
if (err) {
var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
promise._attachExtraTrace(wrapped);
promise._reject(wrapped);
} else if(! multiArgs) { promise._fulfill(value); }else {
var $_len = arguments.length;var args = new Array(Math.max($_len - 1.0)); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i]; }; promise._fulfill(args); } promise =null;
};
}
Copy the code
Apply (_receiver, withAppended(arguments,)) apply(_receiver, withAppended(arguments,)) Apply (this,arguments,fn) where fn is the promise returned by nodebackForPromise, funtion(err,value) is also very similar to node asynchronous functions. So the implementation of this function is to call the callback fn after cb is called and that goes into the promise. We’re going to promise the asynchronous function.