Skip to content

Instantly share code, notes, and snippets.

@jonathan-annett
Last active June 15, 2021 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathan-annett/1a8ae0cc504427317ba2912d2620aae5 to your computer and use it in GitHub Desktop.
Save jonathan-annett/1a8ae0cc504427317ba2912d2620aae5 to your computer and use it in GitHub Desktop.
promising code
function isPromise(p) {
return !!p&&typeof p==='object'&&p.constructor===Promise;
}
function toPromise(p){
return !!p&&typeof p==='object'&&p.constructor===Promise?p:typeof p==='function'&&p.length===2?new Promise(p):Promise.resolve(p);
}
var cpArgs = Array.prototype.slice.call.bind(Array.prototype.slice);
function promiseToCB (nm,fn,THIS) {
if (typeof nm==='function') {
THIS=fn;fn=nm;nm=fn.name;
}
THIS=THIS||this;
const func = function () {
let args = cpArgs(arguments);
if (typeof args[args.length-1]==='function') {
const cb = args.pop();
return fn.apply(THIS,args).then(function(r){
cb (undefined,r);
}).catch(cb);
} else {
return fn.apply(THIS,args);
}
};
Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
if (THIS[nm]) delete THIS[nm];
Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
return func;
}
function cbToPromise (nm,fn,THIS) {
if (typeof nm==='function') {
THIS=fn;fn=nm;nm=fn.name;
}
THIS=THIS||this;
const func = function () {
let args = cpArgs(arguments);
if (typeof args[args.length-1]==='function') {
return fn.apply(THIS,args);
} else {
return new Promise(function(resolve,reject){
args.push(function(err,result){
if (err) return reject(err);
if (arguments.length==2) {
return resolve(result);
}
return resolve(cpArgs(arguments,1));
});
fn.apply(THIS,args);
});
}
};
Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
if (THIS[nm]) delete THIS[nm];
Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
return func;
}
function asPromise (args,resolver,no_err) {
const cb = args[args.length-1],
promise = new Promise(resolver);
return (typeof cb==='function') ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
}
function asCallback (args,wrap,no_err) {
const cb = args[args.length-1],
promise=new Promise(function resolver(resolve,reject) {
return wrap (function (err,result) {
if (err) return reject(err);
resolve(result);
});
});
return (typeof cb==='function') ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
}
@jonathan-annett
Copy link
Author

jonathan-annett commented Jun 15, 2021

write/convert functions that can be called expecting

a cb(error,result) or new Promise (...) format


  • promiseToCB converts and exports an existing function that's been previously coded to return a promise
  • cbToPromise converts and exports an existing function that's been previously coded to call the last argument with (error,result)
    • if wrapped function supplies more than 1 result, the result will be an array of results
    • eg cb(undefined,path,stat) ---> resolve([path,stat]) / cb(undefined,[path,stat])
  • asPromise lets you code a new function to return a promise, but it can be called either way
  • asCallback lets you code a new function to call cb(err,result), but it can be invoked either way

sample functions

each sample takes 2 arguments, and resolves/rejects/errors based on random number.

arg2 can be also be used to force pass or fail. (looks for "-pass" or "-fail").

wrap existing functions

  • exports the function to current "this" (or use promiseToCB(function myFunc(){},newThis); )

    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    

or code new functions, which embed a wrapper.

     function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}

test scipt for above functions

    const local = {}; 
    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    
    function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    const log=console.log.bind(console),info=console.info.bind(console),error=console.error.bind(console);
    
    sampleFunc1("sample1","promise").then (log).catch(error);
    local.sampleFunc2("sample2","promise").then (log).catch(error);
    sampleFunc3("sample3","promise").then (log).catch(error);
    sampleFunc4("sample4","promise").then (log).catch(error);

    sampleFunc1("sample1","callback",info);
    local.sampleFunc2("sample2","callback",info);
    sampleFunc3("sample3","callback",info);
    sampleFunc4("sample4","callback",info);
    
    sampleFunc1("sample1","promise-pass").then (log).catch(error);
    local.sampleFunc2("sample2","promise-pass").then (log).catch(error);
    sampleFunc3("sample3","promise-pass").then (log).catch(error);
    sampleFunc4("sample4","promise-pass").then (log).catch(error);

    sampleFunc1("sample1","callback-pass",info);
    local.sampleFunc2("sample2","callback-pass",info);
    sampleFunc3("sample3","callback-pass",info);
    sampleFunc4("sample4","callback-pass",info);
    
    
    sampleFunc1("sample1","promise-fail").then (log).catch(error);
    local.sampleFunc2("sample2","promise-fail").then (log).catch(error);
    sampleFunc3("sample3","promise-fail").then (log).catch(error);
    sampleFunc4("sample4","promise-fail").then (log).catch(error);
    
    sampleFunc1("sample1","callback-fail",info);
    local.sampleFunc2("sample2","callback-fail",info);
    sampleFunc3("sample3","callback-fail",info);
    sampleFunc4("sample4","callback-fail",info);
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment