我想使用promise,但我有一个回调API,格式如下:

1.DOM加载或其他一次性事件:

window.onload; // set to callback
...
window.onload = function() {

};

2.普通回调:

function request(onChangeHandler) {
    ...
}
request(function() {
    // change happened
    ...
});

3.节点样式回调(“nodeback”):

function getStuff(dat, callback) {
    ...
}
getStuff("dataParam", function(err, data) {
    ...
})

4.具有节点样式回调的整个库:

API;
API.one(function(err, data) {
    API.two(function(err, data2) {
        API.three(function(err, data3) {
            ...
        });
    });
});

我如何在promise中使用API,如何“promise”它?


当前回答

也许已经回答了,但我通常是这样做的:

// given you've defined this `Future` fn somewhere:
const Future = fn => {return new Promise((r,t) => fn(r,t))}

// define an eventFn that takes a promise `resolver`
const eventFn = resolve => {
  // do event related closure actions here. When finally done, call `resolve()`
  something.oneventfired = e => {resolve(e)}
}

// invoke eventFn in an `async` workflowFn using `Future`
// to obtain a `promise` wrapper
const workflowFn = async () => {await Future(eventFn)}

特别是对于indexedDb事件包装器之类的东西,以简化使用。

或者你可能会发现未来的这种变化更具普遍性

class PromiseEx extends Promise {
  resolve(v,...a) {
    this.settled = true; this.settledValue = v;
    return(this.resolve_(v,...a))
  }
  reject(v,...a) {
    this.settled = false; this.settledValue = v;
    return(this.reject_(v,...a))
  }
  static Future(fn,...args) {
    let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
    ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
    return(ft)
  }
}

其他回答

我的promisify版本的回调函数是P函数:

var P=函数(){var self=this;var方法=参数[0];var params=数组.原型.切片.调用(参数,1);return new Promise((resolve,reject)=>{if(method&&typeof(method)==“函数”){params.push(函数(错误,状态){if(!err)返回解析(状态)否则返回拒绝(err);});方法.应用(self,params);}否则返回拒绝(新错误(“不是函数”));});}var callback=函数(par,回调){var rnd=数学地板(Math.random()*2)+1;返回rnd>1?callback(null,par):回调(new Error(“trap”));}callback(“callback”,(err,state)=>错误?console.error(错误):console.log(状态))callback(“callback”,(err,state)=>错误?console.error(错误):console.log(状态))callback(“callback”,(err,state)=>错误?console.error(错误):console.log(状态))callback(“callback”,(err,state)=>错误?console.error(错误):console.log(状态))P(回调,“promise”).then(v=>console.log(v)).catch(e=>console.error(e))P(回调,“promise”).then(v=>console.log(v)).catch(e=>console.error(e))P(回调,“promise”).then(v=>console.log(v)).catch(e=>console.error(e))P(回调,“promise”).then(v=>console.log(v)).catch(e=>console.error(e))

P函数要求回调签名必须是回调(error,result)。

es6 promisify将基于回调的函数转换为基于Promise的函数。

const promisify = require('es6-promisify');

const promisedFn = promisify(callbackedFn, args);

裁判:https://www.npmjs.com/package/es6-promisify

今天,我可以在Node.js中使用Promise作为简单的Javascript方法。

Promise的一个简单而基本的示例(采用KISS方式):

纯Javascript异步API代码:

function divisionAPI (number, divider, successCallback, errorCallback) {

    if (divider == 0) {
        return errorCallback( new Error("Division by zero") )
    }

    successCallback( number / divider )

}

Promise Javascript异步API代码:

function divisionAPI (number, divider) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            return rejected( new Error("Division by zero") )
        }

        fulfilled( number / divider )

     })

}

(我建议访问这个美丽的来源)

此外,Promise可以与ES7中的async\await一起使用,以使程序流等待完整的结果,如下所示:

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


async function foo () {

    var name = await getName(); // awaits for a fulfilled result!

    console.log(name); // the console writes "John Doe" after 3000 milliseconds

}


foo() // calling the foo() method to run the code

使用.then()方法对相同代码的另一种用法

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })

Promise也可以在任何基于Node.js的平台上使用,比如react native。

奖金:混合方法(假设回调方法有两个参数,即error和result)

function divisionAPI (number, divider, callback) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            let error = new Error("Division by zero")
            callback && callback( error )
            return rejected( error )
        }

        let result = number / divider
        callback && callback( null, result )
        fulfilled( result )

     })

}

上面的方法可以响应老式回调和Promise用法的结果。

希望这有帮助。

您可以在ES6中使用本机Promise,例如处理setTimeout:

enqueue(data) {

    const queue = this;
    // returns the Promise
    return new Promise(function (resolve, reject) {
        setTimeout(()=> {
                queue.source.push(data);
                resolve(queue); //call native resolve when finish
            }
            , 10); // resolve() will be called in 10 ms
    });

}

在本例中,Promise没有失败的理由,因此永远不会调用reject()。

死灵一点,这个链接可能有用。。。。


太长,读不下去了看看这个答案末尾的代码片段示例


编写/转换可调用的函数

cb(错误,结果)或新Promise(…)格式


promiseToCB转换并导出先前编码为返回promise的现有函数cbToPromise转换并导出一个先前编码为调用最后一个参数的现有函数(error,result)如果包装函数提供了多个结果,则结果将是一个结果数组例如cb(undefined,path,stat)--->解析([path,stat])/cb(undefine,[path,stat])asPromise允许您编写一个新函数以返回promise,但它可以以任何方式调用asCallback允许您编写一个新函数来调用cb(err,result),但它可以通过任何方式调用

示例函数

每个样本取2个参数,并基于随机数解决/拒绝/错误。

arg2也可以用于强制通过或失败。(查找“-通过”或“-失败”)。

包装现有函数

将函数导出到当前的“this”(或使用promiseToCB(函数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);
    

或者编写嵌入包装器的新函数。

     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);
        
    });}

测试上述功能的scipt


    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);
 

var cpArgs=Array.prototype.slice.call.bind(Array.proto原型.slice);函数promiseToCB(nm,fn,THIS){如果(nm类型==='功能'){这=fn;fn=纳米;nm=fn.name;}此=此||此;const func=函数(){let args=cpArgs(参数);if(参数类型[args.length-1]=='函数'){const cb=args.pop();return fn.apply(THIS,args).then(函数(r){cb(未定义,r);}).捕获(cb);}其他{return fn.apply(THIS,args);}};Object.defineProperty(func,'name',{value:nm,enumerable:false,可配置:true});如果(此[nm])删除此[nm];Object.defineProperty(THIS,nm,{value:func,enumerable:false,可配置:true});返回函数;}函数cbToPromise(nm,fn,THIS){如果(nm类型==='功能'){这=fn;fn=纳米;nm=fn.name;}此=此||此;const func=函数(){let args=cpArgs(参数);if(参数类型[args.length-1]=='函数'){return fn.apply(THIS,args);}其他{return new Promise(函数(解析,拒绝){args.push(函数(错误,结果){if(error)返回reject(err);if(arguments.length==2){返回解析(result);}返回解析(cpArgs(arguments,1));});fn.apply(此,参数);});}};Object.defineProperty(func,'name',{value:nm,enumerable:false,可配置:true});如果(此[nm])删除此[nm];Object.defineProperty(THIS,nm,{value:func,enumerable:false,可配置:true});返回函数;}函数作为Promise(args,解析器,no_err){常量cb=参数[args.length-1],promise=新promise(解析器);return(cb类型=='函数')?promise.then(函数(结果){return cb(no-err,结果)}).catch(cb):promise;}函数作为回调(args,wrap,no_err){常量cb=参数[args.length-1],promise=新promise(函数解析器(resolve,reject){返回换行(函数(错误,结果){if(error)返回reject(err);解决(结果);});});return(cb类型=='函数')?promise.then(函数(结果){return cb(no-err,结果)}).catch(cb):promise;}函数cbPromiseTest(){/*全局样本Func1,样本Func2*/常量local={};promiseToCB(函数sampleFunc1(arg1,arg2){console.log(“决定:”,arg1,arg2);return new Promise(函数(解析,拒绝){const timer=setTimeout(函数(){reject([arg1,arg2,“ouch”].jjoin(“-”);},5000);setTimeout(函数){if(arg2.endsWith(“-pass”)||(!arg2.ends With(”-ffail“)&&Math.random()<0.5)){console.log(“完成:”,arg1,arg2);clearTimeout(计时器);解析([arg1,arg2,“一切正常”].join(“-”));}},2000);});});cbToPromise('sampleFunc2',函数someOtherName(arg1,arg2,cb){console.log(“决定:”,arg1,arg2);const timer=setTimeout(函数){cb([arg1,arg2,“ouch”].jjoin(“-”);},5000);setTimeout(函数){if(arg2.endsWith(“-pass”)||(!arg2.ends With(”-ffail“)&&Math.random()<0.5)){console.log(“完成:”,arg1,arg2);clearTimeout(计时器);cb(未定义,[arg1,arg2,“all good”]。join(“-”));}},2000);},本地);函数sampleFunc3(arg1,arg2){return asPromise(参数,函数(解析,拒绝){console.log(“决定:”,arg1,arg2);const timer=setTimeout(函数(){reject([arg1,arg2,“ouch”].jjoin(“-”);},5000);setTimeout(函数){if(arg2.endsWith(“-pass”)||(!arg2.ends With(”-ffail“)&&Math.random()<0.5)){console.log(“完成:”,arg1,arg2);clearTimeout(计时器);解析([arg1,arg2,“一切正常”].join(“-”));}},2000);});}函数sampleFunc4(arg1,arg2){return asCallback(参数,函数(cb){console.log(“决定:”,arg1,arg2);const timer=setTimeout(函数){cb([arg1,arg2,“ouch”].jjoin(“-”);},5000);setTimeout(函数){if(arg2.endsWith(“-pass”)||(!arg2.ends With(”-ffail“)&&Math.random()<0.5)){console.log(“完成:”,arg1,arg2);clearTimeout(计时器);cb(未定义,[arg1,arg2,“all good”]。join(“-”));}},2000);});}const log=console.log.bind(控制台),info=console.info.bind(控制台,error=console.error.bind);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”,“回调”,信息);local.sampleFunc2(“sample2”,“回调”,信息);sampleFunc3(“sample3”,“回调”,信息);sampleFunc4(“sample4”,“回调”,信息);sampleFunc1(“sample1”,“promise pass”).then(log).catch(error);local.sampleFunc2(“sample2”,“pr”