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.