既存のコールバックAPIをPromiseに変換する方法


How do I convert an existing callback API to promises?
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をどのように使用し、どのように「承諾」しますか?
1階
参照先:https://stackoom.com/question/1WUQK/既存のコールバックAPIをPromiseに変換する方法
2階
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 ES 6 promises:Promise構造関数をサポートする現代のPromiseを使用して実現(例えば、ネイティブES 6 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 ES 6 promises:Promise構造関数をサポートする現代のPromiseを使用して実現(例えば、ネイティブES 6 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が使用されるべきである.
  • #3階
    I don't think the window.onload suggestion by @Benjamin will work all the time, as it doesn't detect whether it is called after the load. @Benjaminのwindow.onloadは、ロード後に呼び出されたかどうかを検出できないため、ずっと有効ではないと思います.I have been bitten by that many times. 私は何度も噛まれた.Here is a version which should always work:常に有効なバージョンです.
    function promiseDOMready() {
        return new Promise(function(resolve) {
            if (document.readyState === "complete") return resolve();
            document.addEventListener("DOMContentLoaded", resolve);
        });
    }
    promiseDOMready().then(initOnLoad);
    
    #4階
    The Q library by kriskowal includes callback-to-promise functions. kriskowalのQライブラリには応答コールバック関数が含まれています.A method like this:このような方法:
    obj.prototype.dosomething(params, cb) {
      ...blah blah...
      cb(error, results);
    }
    
    can be converted with Q.ninvokeはQ.ninvokeで変換できます
    Q.ninvoke(obj,"dosomething",params).
    then(function(results) {
    });
    
    #5階
    You can use JavaScript native promises with Node JS. JavaScriptネイティブPromiseをNode JSと一緒に使用できます.
    My Cloud 9 code link: https://ide.c9.io/adx2803/native-promises-in-node私のCloud 9コードリンク:https://ide.c9.io/adx2803/native-promises-in-node
    /**
    * Created by dixit-lab on 20/6/16.
    */
    
    var express = require('express');
    var request = require('request');   //Simplified HTTP request client.
    
    
    var app = express();
    
    function promisify(url) {
        return new Promise(function (resolve, reject) {
            request.get(url, function (error, response, body) {
                if (!error && response.statusCode == 200) {
                    resolve(body);
                }
                else {
                    reject(error);
                }
            })
        });
    }
    
    //get all the albums of a user who have posted post 100
    app.get('/listAlbums', function (req, res) {
        //get the post with post id 100
        promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
            var obj = JSON.parse(result);
            return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
        })
        .catch(function (e) {
            console.log(e);
        })
        .then(function (result) {
            res.end(result);
        })
    })
    
    var server = app.listen(8081, function () {
        var host = server.address().address
        var port = server.address().port
    
        console.log("Example app listening at http://%s:%s", host, port)
    })
    
    //run webservice on browser : http://localhost:8081/listAlbums
    
    #6階
    When you have a few functions that take a callback and you want them to return a promise instead you can use this function to do the conversion. コールバックが必要な関数がいくつかあり、Promiseを返す場合は、この関数を使用して変換できます.
    function callbackToPromise(func){
    
        return function(){
    
            // change this to use what ever promise lib you are using
            // In this case i'm using angular $q that I exposed on a util module
    
            var defered = util.$q.defer();
    
            var cb = (val) => {
                defered.resolve(val);
            }
    
            var args = Array.prototype.slice.call(arguments);
            args.push(cb);    
            func.apply(this, args);
    
            return defered.promise;
        }
    }