Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

(我想使用Promise,但是我有一个类似以下格式的回调API:)

1. DOM load or other one time event: (1. DOM加载或其他一次事件:)

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

};

2. Plain callback: (2.普通回调:)

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

3. Node style callback ("nodeback"): (3.节点样式回调(“ nodeback”):)

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

4. A whole library with node style callbacks: (4.带有节点样式回调的整个库:)

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

How do I work with the API in promises, how do I "promisify" it? (如何在promise中使用API??,如何“承诺”它?)

  ask by Benjamin Gruenbaum translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
382 views
Welcome To Ask or Share your Answers For Others

1 Answer

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 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 .

(从promise返回函数抛出将迫使您同时使用} catch { .catch 。)

People using promisified APIs do not expect promises to throw.

(使用承诺的API的人们不会期望诺言。)

If you're not sure how async APIs work in JS - please see this answer first.

(如果您不确定JS中异步API的工作方式-请首先查看此答案 。)

1. DOM load or other one time event: (1. DOM加载或其他一次事件:)

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

(因此,创建承诺通常意味着指定何时结算-即何时进入承诺阶段或拒绝阶段以指示数据可用(并且可以通过.then访问)。)

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

(使用支持Promise构造函数的现代Promise实现(例如本机ES6 Promise :)

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

You would then use the resulting promise like so:

(然后,您将使用产生的承诺,如下所示:)

load().then(function() {
    // Do things after onload
});

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

(使用支持延迟的库(让我们在此示例中使用$ q,但稍后我们还将使用jQuery):)

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

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

(或者使用jQuery之类的jQuery,将一次事件挂起:)

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

2. Plain callback: (2.普通回调:)

These APIs are rather common since well… callbacks are common in JS.

(这些API相当常见,因为……在JS中回调很常见。)

Let's look at the common case of having onSuccess and onFail :

(让我们看一下具有onSuccessonFail的常见情况:)

function getUserData(userId, onLoad, onFail) { …

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

(使用支持Promise构造函数的现代Promise实现(例如本机ES6 Promise :)

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

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

(使用支持延迟的库(在此示例中,我们使用jQuery,但上面我们也使用$ q):)

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

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:

(jQuery还提供了$.Deferred(fn)形式,它的优点是允许我们编写一个非常接近new Promise(fn)形式的表达式,如下所示:)

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

Note: Here we exploit the fact that a jQuery deferred's resolve and reject methods are "detachable";

(注意:这里我们利用了一个事实,即jQuery deferred的resolvereject方法是“可分离的”。)

ie.

(即。)

they are bound to the instance of a jQuery.Deferred().

(它们绑定到jQuery.Deferred()的实例 。)

Not all libs offer this feature.

(并非所有库都提供此功能。)

3. Node style callback ("nodeback"): (3.节点样式回调(“ nodeback”):)

Node style callbacks (nodebacks) have a particular format where the callbacks is always the last argument and its first parameter is an error.

(节点样式回调(nodebacks)具有特定的格式,其中回调始终是最后一个参数,而其第一个参数是错误。)

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) reject(err);
            else resolve(data);
        });
    });
}

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

(使用deferred,您可以执行以下操作(尽管本例中Q现在支持您应首选使用的新语法,但让本示例使用Q):)

function getStuffAsync(param) {
    var d = Q.defer();
    getStuff(param, function(err, data) {
        if (err !== null) d.reject(err);
        else d.resolve(data);
    });
    return d.promise;   
}

In general, you should not promisify things manually too much, most promise libraries that were designed with Node in mind as well as native promises in Node 8+ have a built in method for promisifying nodebacks.

(通常,您不应该过多地手动分配内容,大多数基于Node设计的Promise库以及Node 8+中的本机Promise具有内置的用于使NodeBback富集的方法。)

For example

(例如)

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. A whole library with node style callbacks: (4.带有节点样式回调的整个库:)

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实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为promise API很简单:)

Promise.promisifyAll(API);

Or with native promises in Node :

(或在Node中具有本机承诺 :)

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                         .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

Notes:

(笔记:)

  • Of course, when you are in a .then handler you do not need to promisify things.

    (当然,当你在一个.then处理你不需要promisify事情。)

    Returning a promise from a .then handler will resolve or reject with that promise's value.

    (从.then处理程序返回一个诺言将解决或拒绝该诺言的值。)

    Throwing from a .then handler is also good practice and will reject the promise - this is the famous promise throw safety.

    (从.then处理程序中抛出也是很好的做法,并且会拒绝诺言-这就是著名的诺言抛出安全性。)

  • In an actual onload case, you should use addEventListener rather than onX .

    (在实际的onload情况下,应该使用addEventListener而不是onX 。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...