如何将现有的回调API转换为promise? [英] How do I convert an existing callback API to promises?

查看:265
本文介绍了如何将现有的回调API转换为promise?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to work with promises but I have a callback API in a format like:

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

};



2。纯回调:



2. Plain callback:

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



3。节点样式回调(nodeback):



3. Node style callback ("nodeback"):

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

}



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



4. A whole library with node style callbacks:

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

        })
    });
});



如何在promise中使用API​​, promisifyit?


推荐答案

承诺有状态,它们开始作为待处理,可以结算:

Promises have state, they start as pending and can settle to:


  • 已履行,表示计算已成功完成。


  • fulfilled meaning that the computation completed successfully.
  • rejected meaning that the computation failed.

允许返回函数不应该抛出,它们应该返回拒绝promise返回函数将强制您同时使用} catch { a .catch 。使用promisified API的人不希望promise抛出。如果您不确定JS中的异步API是如何工作的,请首先查看此答案

Promise returning functions should never throw, they should return rejections instead. Throwing from a promise returning function will force you to use both a } catch { and a .catch. People using promisified APIs do not expect promises to throw. If you're not sure how async APIs work in JS - please see this answer first.

因此,创建promise通常意味着指定何时结算 - 这意味着当他们移动到已完成或已拒绝阶段以指示数据可以使用 .then )访问。

So, creating promises generally means specifying when they settle - that means when they move to the fulfilled or rejected phase to indicate the data is available (and can be accessed with .then).

c> Promise 构造函数,如原生ES6 promises:

With modern promise implementations that support the Promise constructor like native ES6 promises:

function load(){
    return new Promise(function(resolve,reject){
         window.onload = resolve;
    });
}

使用支持deferred的库(让我们在这里使用$ q,我们也将使用jQuery):

With libraries that support deferred (Let's use $q for this example here, but we'll also use jQuery later):

function load(){
    var d = $q.defer();
    window.onload = function(){ d.resolve(); };
    return d.promise;
}



或者使用jQuery类API,挂钩事件发生一次: p>

Or with a jQuery like API, hooking on an event happening once:

function done(){
    var d = $.Deferred();
    $("#myObject").once("click",function(){
         d.resolve();
    });
    return d.promise();
}



2。平原回调:



这些API是很常见的,因为...回调在JS中很常见。让我们看看 onSuccess onFail 的常见情况:

 function getUserData(userId, onLoad, onFail){ ...


$ b b

现代promise实现支持 Promise 构造函数,如原生ES6 promises:

With modern promise implementations that support the Promise constructor like native ES6 promises:

function getUserDataAsync(userId){
    return new Promise(function(resolve,reject){
         getUserData(userId,resolve,reject);
    });
}

使用支持deferred的库(让我们在这里使用jQuery, 've也使用$ q上面):

With libraries that support deferred (Let's use jQuery for this example here, but we've also used $q above):

function getUserDataAsync(userId){
    var d = $.Deferred();
    getUserData(userId,function(res){ d.resolve(res); } ,function(err){ d.reject(err); });
    return d.promise();
}

jQuery还提供 $。Deferred 表单,其优点是允许我们编写一个非常接近新Promise(fn)表单的表达式,如下所示:

jQuery also offers a $.Deferred(fn) form, which has the advantage of allowing us to write an expression that emulates very closely the new Promise(fn) form, as follows:

function getUserDataAsync(userId) {
    return $.Deferred(function(dfrd) {
        getUserData(userId, dfrd.resolve, dfrd.reject);
    }).promise();
}



注意:这里我们利用一个事实,一个jQuery deferred的 resolve reject 方法是可分离的;即。它们绑定到jQuery.Deferred()的实例。并非所有的库都提供此功能。

Note: Here we exploit the fact that a jQuery deferred's resolve and reject methods are "detachable"; ie. they are bound to the instance of a jQuery.Deferred(). Not all libs offer this feature.

节点样式回调(nodebacks)具有特定格式,其中回调始终是最后一个参数,其第一个参数是错误。让我们先手动进行promisify:

Node style callbacks (nodebacks) have a particular format where the callbacks is always the last argument and its first parameter is an error. Let's first promisify one manually:

getStuff("dataParam",function(err,data){

To:

function getStuffAsync(param){
    return new Promise(function(resolve,reject){
         getStuff(param,function(err,data){
             if(err !== null) return reject(err);
             resolve(data);
         });
    });
}

$ b有了延迟,你可以做以下(让我们使用Q这个例子,虽然Q现在支持你应该喜欢的新语法):

With deferreds you can do the following (let's use Q for this example, although Q now supports the new syntax which you should prefer):

function getStuffAsync(param){
    var d = Q.defer();
    getStuff(param,function(err,data){
         if(err !== null) return d.reject(err); // `throw err` also works here.
             d.resolve(data);
    });
    return d.promise;   
}

一般来说,你不应该手动过多地承诺,设计了Node的库有一个内置的方法来承诺nodeback。例如

In general, you should not promisify things manually too much, most promise libraries that were designed with Node in mind have a built in method for promisifying nodebacks. For example

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q



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



这里没有黄金规则,你一个一个地承诺它们。然而,一些promise实现允许你这样做批量,例如在蓝鸟,将nodeback API转换为promise API是简单的:

4. A whole library with node style callbacks:

There is no golden rule here, you promisify them one by one. However, some promise implementations allow you to do this in bulk, for example in Bluebird, converting a nodeback API to a promise API is as simple as:

Promise.promisifyAll(API);

注意:


  • 当然,当你在 .then 处理程序中时,你不需要承诺。从 .then 处理程序返回一个promise将解析或拒绝该promise的值。从 .then 处理程序抛出也是好的做法,并将拒绝承诺 - 这是着名的承诺抛出安全。

  • 在实际 onload 中,您应该使用 addEventListener code> onX 。

  • Of course, when you are in a .then handler you do not need to promisify things. Returning a promise from a .then handler will resolve or reject with that promise's value. Throwing from a .then handler is also good practice and will reject the promise - this is the famous promise throw safety.
  • In an actual onload case, you should use addEventListener rather than onX.

这篇关于如何将现有的回调API转换为promise?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆