非同期プログラミングを約束も強い従来のソリューションより合理的な解決策、[コールバック関数とイベント]は
大きいです。
---この記事の抜粋ルアンYifeng「のECMAScript 6標準入門」
プロミスの意味
Hunzi約束は、フロントは、単に将来的にいつか終わるイベント(通常は非同期操作)の結果を保持するコンテナ、だと思います。
プロミスオブジェクトは、次の2つの特徴があります。
- 外部の影響から、オブジェクトの状態:
:約束は、非同期操作を表し、三つの状態があります
保留:継続的な
解決:完成し、また成就知ら
拒否:失敗した
だけで非同期操作の結果は、あなたは現在の状態の種類、いずれかを決定することができますその他の動作は、この状態を変更することはできません。 - この結果を得ることができますステータス変更したら、それはいつでも変更されることはありません。
プロミスオブジェクトの状態が変化し、2つだけの可能性:
1.保留からは解決済みに変更
保留が拒否から変更2.
限り、これら二つのものが凝固状態に起こる、それは変更されることはありませんし、その結果を維持するとして。
もちろん、フロントエンドHunziの約束は、いくつかの欠点があると思います。
- あなたは約束をキャンセルすることはできません新しいが途中でキャンセルすることができないと、それが直ちに実行されます。
- あなたは、コールバック関数、内部の約束スローエラーを設定しない場合、それは外部には反応しません。
- 保留状態にあるものの、進展は現在、どこのステージを知る方法はありません。
基本的な使い方
ES6プロミスオブジェクトはコードを見て、約束の例を生成するコンストラクタで、所定。
JS code:
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */) {
resolve(value);
} else {
reject(error);
}
});
复制代码
説明:
プロミスコンストラクタは、パラメータとして関数を受け取り、2つのパラメータは、関数解決していると拒否します。
- 解決関数:パラメータとして配ることを約束からオブジェクトの状態、成功したコールの非同期動作時に「成功」(保留からResolvedに、すなわち、変更)、および非同期動作の結果に「未完」。
- 機能を拒否:プロミス「未完」からオブジェクトの状態は、(拒否保留から、すなわち、変更)を「失敗」に、出て通過するためのパラメータとして、非同期操作が失敗したときに呼び出され、非同期動作のエラーがあってもよいです。
プロミスインスタンス生成後、この方法は、各状態に指定することができ、コールバック関数は、コードを見て、状態を拒否解決さ:
JS code:
promise.then(function(value) {
// success
}, function(error) {
// failure
});
复制代码
説明:
2つのコールバックメソッドは、引数として受け入れることができます。状態が解決されたオブジェクトの約束になったときに最初のコールバック関数は、状態は、オブジェクトプロミスが拒否になったときに2番目のコールバック関数が呼び出され、呼び出されます。第二の機能はオプションで提供する必要はないことを特徴とします。
私たちは約束して、一般的に非同期ロードの写真で使用される私たちのプロジェクトを実現し、Ajaxの動作を実現するために多くのシーン、Hunziフロントエンドの使用をシミュレートすることができます約束します。
以下は、コードを見て、絵の非同期ロードの例を示します。
JS code:
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
复制代码
説明:使用非同期操作の約束は、ロードされた画像をラップします。負荷が成功すれば、それはそれ以外の場合は、メソッドを呼び出す拒否、解決メソッドを呼び出します。
次のAjaxプロミスオブジェクトと操作の実装の一例であり、コードを見て:
JS code:
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
复制代码
说明:
getJSON XMLHttpRequestオブジェクトは、HTTP JSONデータの要求を発行するための、パッケージ化することであり、プロミスオブジェクトを返します。
Promise.prototype.then()
方法の例は、次に、プロミスは、この方法は、プロトタイプオブジェクトPromise.prototypeで定義されています。その役割は、状態変化約束インスタンスに対してコールバック関数を追加することです。
次いで、この方法は、2つのパラメータを受け取ります。
- 解決済みステータスコールバック関数
- (オプション)状態を拒否されたコールバック関数です
、その後、再び本方法は、別の方法、コードビューを呼び出し、すなわち、チェーンを使用して書くことができる:(いない元のインスタンスプロミスPS)メソッドは、新しいインスタンスの約束を返します。
JS code:
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
}); 复制代码
説明:コードを順次2つのコールバック関数を指定し、次に方法を使用しては、コールバック関数の完了後、結果は、2番目のコールバックに渡されたパラメータとして返されます。
チェーンは、その後を使用して、あなたが呼ばれるためには、コールバック関数のセットを指定することができます。このとき、コールバック関数の前に、約束のオブジェクトが残っている(つまり、非同期操作です)返すことがあり、その後、コールバック関数の後に、それは約束オブジェクトの状態変化を待つことになる、と呼ばれます。
そして、コードを見て、コールバック関数のオプションパラメータを見てみましょう。
JS code:
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log("Resolved: ", comments);
}, function funcB(err){
console.log("Rejected: ", err);
});
复制代码
説明:
最初のメソッド指定されたコールバック関数は、プロミスが別の目的である返します。このとき、2番目のメソッド指定されたコールバック関数は、新しい約束オブジェクトの状態変化を待ちます。あなたは解決済みとなった場合は拒否され、funcBの機能へのステータス変更が呼び出された場合、funcAと関数が呼び出されます。
Promise.prototype.catch()
Promise.prototype.catchが.thenれる(ヌル、拒絶)エラーが発生したコールバック関数を指定するために使用される別名は、コードを見て:
JS code:
getJSON("/posts.json").then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
复制代码
説明:getJSONの オブジェクトの状態が変化する場合、メソッドは、プロミスオブジェクトを返します
Promise.all()
新しいインスタンスにパッケージ化された複数のインスタンスの約束、約束のためのPromise.all方法は、コードを見て:
JS code:
var p = Promise.all([p1, p2, p3]);
复制代码
説明: Promise.allの メソッドは、パラメータとして配列を受け取り、P1、P2、P3 インスタンスがプロミスオブジェクトでない場合、それは最初に下記呼ぶ Promise.resolveの 方法、プロミスインスタンスにパラメータを、更なる処理を。Promise.allの メソッドパラメータは、アレイではないかもしれないが、イテレータインターフェースを持っている必要があり、各部材は、プロミスのインスタンスを戻します。
PがP1、P2、P3の状態によって決定される、2例に分割されます。
- 唯一のP1、P2、P3の状態の成就となっている、状態がPになります
- 限りP1、P2、P3間のようになっています
例を見てください:
JS code:
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON("/post/" + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
复制代码
説明:プロミスであるプロミス例のアレイ、6つのインスタンスの状態だけになっている6備え 成就、またはAとなっています
Promise.race()
この方法はまた、コードを見て、新しいインスタンスにパッケージ複数のインスタンスプロミス、プロミスをPromise.race。
JS code:
var p = Promise.race([p1, p2, p3]);复制代码
説明:限り P1、P2、P3 の状態を変更する最初のうちの1つのインスタンス、P-は、 状態は、それに応じて変化します。変更することが最初のインスタンスの値を返すことを約束し、それが渡され たpコールバック関数。
Promise.raceメソッドのパラメータとインスタンスを約束されていない場合、Promise.resolveメソッドを呼び出します、とPromise.all同じように、約束のインスタンスへのパラメータは、処理を行います。
Promise.resolve()
時には、既存のオブジェクトは、例を見て、この役割を果たしていると、オブジェクトを約束Promise.resolve方法オンにする必要があります。
JS code:
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
复制代码
注:上記のコードは、新しいオブジェクトに遅延jQueryオブジェクトの約束を生成しました。
4例にPromise.resolveメソッドのパラメータ。
- パラメータは、約束の一例で
、パラメータは約束のインスタンスである場合、Promise.resolveは任意の変更を行うことはありません、このインスタンスそのまま返されます。 - パラメータ被験者はthenable
thenable目的は、コードを見て、この方法を有する物体を指します。
JS code:
let thenable = {
then: function(resolve, reject) {
resolve(2);
}
};
复制代码
説明: Promise.resolve正方形方法プロミスは、オブジェクトにオブジェクトで、その後すぐに実行します
-
パラメータはありませ次に、オブジェクトメソッド、または単にないオブジェクトパラメータがプリミティブ値またはオブジェクトであれば、方法、Promise.resolveを持っていません
JS code:
var p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello复制代码
説明:文字列「こんにちは」は 、非同期操作に属していない、状態約束インスタンスからの戻りが発生した 解決への コールバック関数が即座に実行されるように、。
- パラメータ
Promise.resolveプロミス対象方法は、パラメータなし、直接リターン解決された状態との通話を可能にしません。
Promise.reject()
Promise.reject(理由)メソッドは、インスタンスの状態が拒否され、新たな約束のインスタンスを返します。その使用パラメータ及び方法は、コードを見て、まったく同じPromise.resolve:
JS code:
var p = Promise.reject('出错了');
// 等同于:
var p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s){
console.log(s)
});
// 出错了
复制代码
説明:オブジェクトPの約束のインスタンスを生成する状態をされ、 拒否され、コールバック関数が直ちに実行されます。
便利な二つの追加方法
()で行わ
説明:に主題を約束 その後、
JS code:
Promise.prototype.done = function (onFulfilled, onRejected) {
this.then(onFulfilled, onRejected)
.catch(function (reason) {
// 抛出一个全局错误
setTimeout(() => { throw reason }, 0);
});
};
复制代码
説明:doneメソッド、できる限り それから 提供するための方法として、 成就を
最後に()
最後に関係なく、プロミス最終状態を標的化するために使用される方法の動作は、指定され実行されます。
方法との最大の違いを行わ:それは関数が実行されなければならない、パラメータとして通常のコールバック関数を取ります。
コードを見てください:
JS code:
server.listen(0)
.then(function () {
// run test
})
.finally(server.stop);
复制代码
手書きの約束
最後に、技術やインタビュー記事がしばしば言及した手書きの約束を探求するかどうか、私たちに手を差し伸べる、実際には、私たちはコードを見て、書かれた以上をまとめることができると信じて:
JS code:
function myPromise(constructor){
let self = this;
self.status = 'pending'; // 定义状态改变前的初始状态
self.value = undefined; // 定义状态为resolved时候的状态
self.reason = undefined; // 定义状态为rejected时候的状态
function resolve(value) {
if(self.status === 'pending'){ // 两个函数判断等于pending, 保证了状态的改变是不可逆的
self.value = value;
self.status = 'resolved';
}
}
function reject(reason) {
if(self.status === 'pending'){ // 两个函数判断等于pending, 保证了状态的改变是不可逆的
self.value = reason;
self.status = 'rejected';
}
}
// 捕获构造异常
try{
constructor(resolve, reject);
}catch{
reject(e);
}
}
myPromise.prototype.then = function(onFullfilled, onRejected){
let self = this;
switch(self.status){
case 'resolved':
onFullfilled(self.value);
break;
case 'rejected':
onRejected(self.reason);
break;
}
}
var p = new myPromise(function(resolve, reject){
resolve(1)
});
p.then(function(x){
console.log(x)
});
复制代码
まあ、それはフロントHunziが約束歓迎の親指とエラー訂正に関する知識をまとめます。
最後に、私はすべての幸せな日々あなたがしたいです!
( ハートOS:で滞在するために、2日間の休暇があります)
ます。https://juejin.im/post/5d08a8baf265da1ba647eea7で再現