既存のコールバックAPIをPromiseに変換する方法
11875 ワード
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ロードまたは他のイベント:
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
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
With modern promise implementations that support the
These APIs are rather common since well… callbacks are common in JS. これらのAPIはかなりよく見られます.JSではコールバックがよく見られるからです.Let's look at the common case of having
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:まず手動で割り当てましょう.
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に変換するなど、この操作を一括して実行できます. Of course, when you are in a In an actual #3階
I don't think the
The Q library by kriskowal includes callback-to-promise functions. kriskowalのQライブラリには応答コールバック関数が含まれています.A method like this:このような方法:
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
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を返す場合は、この関数を使用して変換できます.
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:保留中の状態から解決できる状態を約束する:
} 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
:onSuccess
とonFail
を持つ一般的な状況を見てみましょう.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のresolve
とreject
の方法が「分離可能」であるという事実を利用した.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:メモ:.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
プロセッサから投げ出すのも良い方法であり、約束を拒否します.これは有名な約束であり、セキュリティを投げ出すことです.onload
case, you should use addEventListener
rather than onX
. 実際のonload
の場合、addEventListener
ではなくonX
が使用されるべきである.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;
}
}