手書きで簡単なPromise
7978 ワード
今日は突発的に考えました.自分でPromiseを書いて遊びに来たいです.書くと反応がよくないです.とりあえずPromiseを見てみます.
まず棚を書きます.上の使用例を見てください.基本的に必要なものは必ず次のようなものがあります.構造関数、一つのthen関数、一つのcatch関数、そして上のようにreolveとrejectもPromiseが提供しているはずです.はthenを実行した後にcatchを実行して、Promiseの状態はpendingからrejectとreolveの中の一つになるだけで、しかも変化した後に を変えることができません.私達が書いたPromiseはthenとcatchを同期して実行します. は、reolveとrejectに伝えられた値は、thenとcatchが呼び出されたときに に渡されていません.
まず状態の問題を解決して、現在の状態を表す変数を加えます.promisestatusは、構造関数に初期状態pendingを追加し、reolve、reject、then、catchに状態判断と状態設定を追加します.
まずどのように構造を伝達するかを見てみます.reolveとrejectのパラメータを一つ追加します.promiseValue変数レシオの前にエラーが発生しました.このようなcatchがあれば、捕獲しません.そして、rejectが誰も接続されていません.thenの内容は を実行しません.レスリング後にエラーが発生しました.このようなcatchがあっても捕れないし、捨てられないです. を食べました. rejectの前にエラーが発生しました.catchがないとエラーを投げます.そしてrejectには誰も来ていません.もしcatchがあったら、エラーは捕獲され、rejectは無視され、catchを入れてもreject を無視できます. rejectの後でエラーが発生しました.catchがないとエラーを投げます.そしてrejectには誰も来ていません.もしcatchがあったら、エラーが食べられます.このcatchは処理されます.もっと多くのcatchを入れても大丈夫です. 上の4の中は全部簡単な情況で、thenとcatchの中で誤りがあるならば、基本的にまた分けてcatchが来るかどうかの情況があって、情況は比較的に多くて、みんなは自分で試してみることができて、比較的に面白いです.
こちらで処理したのはそんなにひどくないです.簡単に処理して、構造関数の中のコールバックをtry...catchに包んでみました.thenに判断を追加しました.promiseValueはエラーです.直接に過ぎます.thenの関数を実行しないで、catchでエラーをtry...catchします. レスリングの前にエラーが発生しました.キャッチャーがあります.食べられませんでした. レスリング後にエラーが発生しました.同じ です. reject前にエラーが発生しました.catchがないと食べられます.rejectは無視されます.もしcatchがあったら、エラーは捕獲され、rejectは無視され、catchを入れてもreject を無視できます. rejectの後で間違えて、catchがないと食べられます.rejectは無視されます.もしcatchがあったら、エラーは捕獲されます.rejectは無視されます.catchを入れるとrejectを処理します. 複雑な状況はテストしません.とにかく原生とは大きく違っています.
私達は実はまた面白いことを発見しました.原生のPromiseのresoveとrejectは自分で書き換えることができます.もちろん直してから正常な流れがいけなくなりました.
私達の最終バージョンはこのようです.
=================を見て、このコードに問題があると言って、テスト用のサンプルを提供しました.瞬間的に顔を打つというのは、同期の論理が書かれています.thenとcatchが先に実行されます.setTimeoutがresoliveを実行する時に、thenとcatchが全部実行されました.コンストラクションでリガのcalback配列ができます.thenとcatchは全部calbackの中にpushします.でもここでは書きません.規範を見てから問題が多すぎます.
let pp= new Promise((resolve, reject) => {
resolve('done');
});
pp.then((value) => {
console.log(value);
}).catch((e)=>{
console.log(e);
});
基本的な書き方は大体このようです.Promiseをよく見ると、やはり変です.例えば、パラメータは一つの関数です.この関数は二つのパラメータresoveとrejectがあります.この二つのパラメータも関数です.また、私達が呼出しなければこのPromiseは役に立たないです.thenとcatchの中のものも実行できません.この二つのパラメータはPromiseから提供されたもので、Promise実行プロセスの一部ですが、どうやって書くべきか分かりません.でも、まず行動してから書いたらいいかもしれません.まず棚を書きます.上の使用例を見てください.基本的に必要なものは必ず次のようなものがあります.構造関数、一つのthen関数、一つのcatch関数、そして上のようにreolveとrejectもPromiseが提供しているはずです.
function helloPromise(cb) {
cb();
return {then: this.then, catch: this.catch}; //
}
helloPromise.prototype.then = function (cb){
cb();
}
helloPromise.prototype.catch = function (cb){
cb();
}
helloPromise.prototype.resolve = function (arg){
}
helloPromise.prototype.reject = function (arg){
}
その後、私たちは例を挙げて実行してみましたが、レレスは関数ではないということが分かりました.見に行くと、今のコンストラクタの中でレレスとレジェクトを加えて、このようになりました.function helloPromise(cb) {
cb(this.resolve, this.reject);
return {then: this.then, catch: this.catch};
}
もう一度実行してください.undefinedが出力されています.エラーが発生しました.このundefinedはpp.then((value) => {
console.log(value);
})
この文章は印刷しました.このエラーは後ろのcatchです.thenは何も戻っていないので、catchは本体が見つからないです.thenとcatchを変えます.helloPromise.prototype.then = function (cb){
cb();
return new helloPromise(function(resolve, reject) {});
}
もうちょっと実行してください.わあ、少なくとも間違えないように、undefined二つを出力しました.ここまでいくつかの問題があります.まず状態の問題を解決して、現在の状態を表す変数を加えます.promisestatusは、構造関数に初期状態pendingを追加し、reolve、reject、then、catchに状態判断と状態設定を追加します.
function helloPromise(cb) {
this._promiseStatus = 'pending';
cb(this.resolve, this.reject);
return {then: this.then, catch: this.catch};
}
helloPromise.prototype.resolve = function (arg){
if(this._promiseStatus === 'pending'){
this._promiseStatus = 'fulfilled';
}
}
helloPromise.prototype.then = function (cb){
if(this._promiseStatus === 'fulfilled'){
cb();
}
return new helloPromise(function(resolve, reject) {});
}
この時私達が運転してみたら、私達が望む結果とは違って、ここにはたくさんのthisバインディング問題があります.だから、コンストラクタでバインドしてみます.function helloPromise(cb) {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
this.then = this.then.bind(this);
this.catch = this.catch.bind(this);
this._promiseStatus = 'pending';
cb(this.resolve, this.reject);
return {then: this.then, catch: this.catch};
}
運転してください.reolveを発見した時は大丈夫です.rejectに問題があります.thenとcatchで返した値に問題があるので、thisに戻ります.helloPromise.prototype.then = function (cb){
if(this._promiseStatus === 'fulfilled'){
cb();
}
return this;
}
このように状態もよく伝えられます.(でも、標準と違って顔を隠します.)ここでもう一つの問題があります.catchの行為です.複数のcatchがあれば、元のPromiseは第一個だけ実行します.もしcatchがないなら、エラーは投げられます.この部分はまず見ません.まずどのように構造を伝達するかを見てみます.reolveとrejectのパラメータを一つ追加します.promiseValue変数
helloPromise.prototype.resolve = function (arg){
if(this._promiseStatus === 'pending'){
this._promiseStatus = 'fulfilled';
this._promiseValue = arg;
}
}
helloPromise.prototype.then = function (cb){
if(this._promiseStatus === 'fulfilled'){
this._promiseValue = cb(this._promiseValue);
}
return this;
}
このように私達の基本的なPromiseの様子はすでにあって、その後私達は誤りを処理しにきて、まず原生のPromiseの行為を見て、間違いの情況はこのようにいくつあります:こちらで処理したのはそんなにひどくないです.簡単に処理して、構造関数の中のコールバックをtry...catchに包んでみました.thenに判断を追加しました.promiseValueはエラーです.直接に過ぎます.thenの関数を実行しないで、catchでエラーをtry...catchします.
function helloPromise(cb) {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
this.catch = this.catch.bind(this);
this.then = this.then.bind(this);
this._promiseStatus = 'pending';
try{
cb(this.resolve, this.reject);
}catch(e){
this._promiseValue = e;
}
return {then: this.then, catch: this.catch};
}
helloPromise.prototype.then = function (cb){
if(toString.call(this._promiseValue) === '[object Error]'){
return this;
}
if(this._promiseStatus === 'fulfilled'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
}
return this;
}
helloPromise.prototype.catch = function (cb){
if(toString.call(this._promiseValue) === '[object Error]'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
return this;
}
if(this._promiseStatus === 'rejected'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
}
return this;
}
原生と比べてみよう.私達は実はまた面白いことを発見しました.原生のPromiseのresoveとrejectは自分で書き換えることができます.もちろん直してから正常な流れがいけなくなりました.
私達の最終バージョンはこのようです.
function helloPromise(cb) {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
this.catch = this.catch.bind(this);
this.then = this.then.bind(this);
this._promiseStatus = 'pending';
try{
cb(this.resolve, this.reject);
}catch(e){
this._promiseValue = e;
}
return {then: this.then, catch: this.catch};
}
helloPromise.prototype.then = function (cb){
if(toString.call(this._promiseValue) === '[object Error]'){
return this;
}
if(this._promiseStatus === 'fulfilled'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
}
return this;
}
helloPromise.prototype.catch = function (cb){
if(toString.call(this._promiseValue) === '[object Error]'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
return this;
}
if(this._promiseStatus === 'rejected'){
try{
this._promiseValue = cb(this._promiseValue);
}catch(e){
this._promiseValue = e;
}
}
return this;
}
helloPromise.prototype.resolve = function (arg){
if(this._promiseStatus === 'pending'){
this._promiseStatus = 'fulfilled';
this._promiseValue = arg;
}
}
helloPromise.prototype.reject = function (arg){
if(this._promiseStatus === 'pending'){
this._promiseStatus = 'rejected';
this._promiseValue = arg;
}
}
卵はあまり使いません=================を見て、このコードに問題があると言って、テスト用のサンプルを提供しました.瞬間的に顔を打つというのは、同期の論理が書かれています.thenとcatchが先に実行されます.setTimeoutがresoliveを実行する時に、thenとcatchが全部実行されました.コンストラクションでリガのcalback配列ができます.thenとcatchは全部calbackの中にpushします.でもここでは書きません.規範を見てから問題が多すぎます.
let pp= new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('done')
},100);
});
pp.then((value) => {
console.log(value);
}).catch((e)=>{
console.log(e);
});