プロミスには状態があり、保留中として開始され、次のように解決できます。
- 計算が正常に完了したことを意味します。
- rejectは、計算が失敗したことを意味します。
Promise を返す関数は をスローしてはならず、代わりに拒否を返す必要があります。プロミスを返す関数からスローすると、 a} catch {
とa の両方を使用する必要があり.catch
ます。Promisified API を使用している人は、Promise がスローされることを期待していません。JS で非同期 API がどのように機能するかがわからない場合は、まずこの回答を参照してください。
1. DOM ロードまたはその他の 1 回限りのイベント:
したがって、Promise を作成するということは、通常、いつ決済するかを指定することを意味します。つまり、データが利用可能 (および でアクセスできる.then
) であることを示すために、いつ履行または拒否フェーズに移行するかを意味します。
Promise
ネイティブ ES6 promise のようなコンストラクターをサポートする最新の promise 実装では:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
次に、結果のプロミスを次のように使用します。
load().then(function() {
// Do things after onload
});
deferred をサポートするライブラリの場合 (この例では $q を使用しますが、後で jQuery も使用します):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
または、jQuery のような API を使用して、一度発生したイベントにフックします。
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. 単純なコールバック:
これらの API はかなり一般的です... JS ではコールバックが一般的です。onSuccess
とを持つ一般的なケースを見てみましょうonFail
:
function getUserData(userId, onLoad, onFail) { …
Promise
ネイティブ ES6 promise のようなコンストラクターをサポートする最新の promise 実装では:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
deferred をサポートするライブラリ (ここではこの例では jQuery を使用しますが、上記では $q も使用しています):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery はフォームも提供します。これには、次のように、フォーム$.Deferred(fn)
に非常によく似た式を記述できるという利点があります。new Promise(fn)
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
注: ここでは、jQuery の deferredメソッドresolve
とreject
メソッドが「分離可能」であるという事実を利用します。すなわち。それらはjQuery.Deferred()のインスタンスにバインドされます。すべてのライブラリがこの機能を提供しているわけではありません。
3. ノード スタイルのコールバック (「nodeback」):
ノード スタイルのコールバック (ノードバック) には、コールバックが常に最後の引数であり、最初のパラメーターがエラーであるという特定の形式があります。最初に手動で約束しましょう:
getStuff("dataParam", function(err, data) { …
に:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
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;
}
一般に、手動でプロミスを行いすぎないようにしてください。Node 8+ のネイティブ Promise と同様に、Node を念頭に置いて設計されたほとんどの Promise ライブラリには、ノードバックを Promisify するためのメソッドが組み込まれています。例えば
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. ノード スタイルのコールバックを含むライブラリ全体:
ここには黄金律はありません。1 つずつ約束します。ただし、いくつかの promise 実装では、これを一括で実行できます。たとえば、Bluebird では、nodeback API を promise API に変換するのは次のように簡単です。
Promise.promisifyAll(API);
またはNodeのネイティブ promiseを使用:
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}), {});
ノート:
- もちろん、
.then
ハンドラーにいるときは、約束する必要はありません。ハンドラーから promise を返す.then
と、その promise の値で解決または拒否されます。ハンドラーから.then
スローすることも良い習慣であり、promise を拒否します。これは、有名なプロミス スロー セーフティです。
- 実際には、ではなく
onload
を使用する必要があります。addEventListener
onX