教えてあげます.一歩ずつPromiseを実現します.

15307 ワード

Promiseは今みんなよく知っていると思います.主な役割は非同期の問題を解決することです.ここで簡単に紹介します.
Promise仕様はCommonJS仕様の一つです.Promise仕様はPromises/A、Promises/B、Promises/Kissなど様々な種類があります.
興味のある人はここに来てもっと知ることができます. http://wiki.commonjs.org/wiki/Promises
今流行しているのはPromise/A仕様です.人々はその完璧さと拡張され、次第にPromise/A+規範を形成しました.
ここの規則は何ですか?ここに行って調べてみてください.
http://promises-aplus.github.io/promises-spec/
http://hussion.me/2013/10/19/promises-a/
今はブラウザ内蔵のPromiseをサポートしています.そのアプリの文法はここで調べられます.
http://www.html5rocks.com/zh/tutorials/es6/promises/#toc-app
そのアプリを見ることができますが、そんなに多くはないです.大体重要な点をつかんで十分だと思います.
1、promiseには3つの状態があります.待機、完了、拒否されました.
2、promiseの状態は「待ち」から「完了」または「拒否」にしか変えられません.逆変換はできません.同時に「完了」と「拒絶」も互いに変換できません.
3、promiseはthen方法が必要であり、またpromiseに戻ります.thenのチェーン呼び出し、つまりthenableのです.
4、thenは2つのフィードバック(成功と拒否)を受け入れ、対応する状態の変化に触発され、フィードバックはプロミセに戻り、このプロミセがresolovedされるのを待って、thenチェーンを引き続きトリガします.
これらの重要な特徴を知ると、ブラウザに内蔵されているアプリを参考にして実現できます.
私たちはあまり規則に縛られなくてもいいです.まず自分の考えに従ってください.
promiseの使用は大体次の通りです.
var promise = new Promise(function(resolve, reject) {
	setTimeout(function(){
		resolve('val')
	});
});

promise.then(onFulfilled,onRejected).then(onFulfilled,onRejected)
主な考え方は私達が直接に帰ってきたpromiseオブジェクトを操作することができます.
ここの関数はすぐには実行されません.列に参加して、将来のある時間を待つときに実行されます.
以上の説明があれば、実現できます.
最初に3つの状態を定義します.
var PENDING=undefined、FUL FILLED=1、REJECTED=2
次にPromiseコンストラクタを実現します.この関数は関数パラメータを受け入れます.関数パラメータは私たちが提供する二つの方法を受け入れます.
使用者が将来のある時間に私たちのキューを実行するためにトリガを呼び出します.ここでは現在の状態、転送の値を初期化します.
およびthen時に保存されたキュー.
大体次のように
var Promise = function(resolver){
    if (!isFunction(resolver))
        throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
    if(!(this instanceof Promise)) return new Promise(resolver);

    var promise = this;
    promise._value;
    promise._reason;
    promise._status = PENDING;
    promise._resolves = [];
    promise._rejects = [];
    
    var resolve = function(value){
        //     FULFILLED 
        //  then    _resolves    ,
        //        ,    _value
    }
    var reject = function(reason){
        //     REJECTED
        //  then    _rejects    ,
        //        ,    _rejects
    }
    
    resolver(resolve,reject);
}
これがあれば、私たちはthenを実現したらokです.
thenでやるべきことはプロミセを返してthenに送るチェーンコールです.
また、プロミゼ.then(オンフルフィlled、オンリージェクト)の場合は、現在のプロミスの状態を判断します.
pendingであればonFulfilledとonRejecedを_に追加します.reolvesと_reject配列には、
さもないと、状態によって、直接にフィードバックを触発します.ここで注意すべきことは、プロミセが戻ってきたら、私たちはこのプロミセがレレスされるまで待ちます.
thenチェーンの次のpromiseをトリガーして実行します.
コードは大体このようです.
Promise.prototype.then = function(onFulfilled,onRejected){
    var promise = this;
    //       promise,    thenable 
    return Promise(function(resolve,reject){
        function callback(value){
          var ret = isFunction(onFulfilled) && onFulfilled(value) || value;
          if(isThenable(ret)){
              //      promise     ,     promise     
            ret.then(function(value){
               resolve(value); 
            },function(reason){
               reject(reason);
            });
          }else{
            resolve(ret);
          }
        }
        function errback(reason){
            reason = isFunction(onRejected) && onRejected(reason) || reason;
            reject(reason);
        }
        if(promise._status === PENDING){
               promise._resolves.push(callback);
               promise._rejects.push(errback);
           }else if(promise._status === FULFILLED){ //       then  ,    
               callback(promise._value);
           }else if(promise._status === REJECTED){
               errback(promise._reason);
           }
    });
}
ここで説明します
var isThe nable=function(obj){return obj&typeof obj['then'='function';
つまり、戻ってきた相手はthen方法を持っています.私たちはpromiseの対象とします.
ここまで私達の主要な仕事は完成しました.他のall、raceなどの方法は全部簡単です.具体的にここに来て完全な実現を見ることができます.
https://github.com/ygm125/promise/blob/master/promise.js
いくつかの例を挙げて、効果を見てみましょう.
var getData100 = function(){
    return Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('100ms');
        },100);
    });
}

var getData200 = function(){
    return Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('200ms');
        },200);
    });
}

getData100().then(function(data){
    console.log(data); // 100ms
    return getData200();
}).then(function(data){
    console.log(data); // 200ms
    return data + data;
}).then(function(data){
    console.log(data) // 200ms200ms
});
もちろん直接getData 100().then(getData 200).then(function(val){}ができます.
thenは一つだけ伝えてもいいです.成功したコールバックを受けてもいいです.catch方法で失敗のコールを受けてもいいです.
catchはthenのシンタックス飴で、promise.thenに相当します.
allで並行して実行することもできます.
Promise.all([getData100(),getData200()]).then(function(value){
    console.log(value) // ['100ms','200ms']
});
結果の順序は伝来の順序と同じである.
私達も直接にobjを値とする成功状態のpromiseを作成できます.
Promise.resolve('FULFILLED').then(function(val){
    console.log(val) // FULFILLED
});
実現はとても簡単です.コードを見れば分かります.
ここでもいくつかの面白いものを作ることができます.例えばdelay方法を作ることです.
Promise.prototype.delay = function(ms){
    return this.then(function(val){
        return Promise.delay(ms,val);
    })
}

Promise.delay = function(ms,val){
    return Promise(function(resolve,reject){
        setTimeout(function(){
            resolve(val);
        },ms);
    })
}
何ミリ秒ごとに操作ができますか?
Promise.delay(1000).then(function(){
    //     
}).delay(1000).then(function(){
    //     
})
私達も一つの循環を包装して、何回実行しますか?毎回何秒遅延しますか?
 

<script type=「text/javascript」>
!function(a,b){var c=b,d=1,e=2,f=function(a){return"function==typeof a)、g=function(a){return"==Object Aray===Object.prototype.String.call(a)=function=================================funcncncncefffffftttttject=funcncncncnction""""===================================ustatus==c&set Timeout(function(){d.ustatus=a,j.call(d,b)}、j=function(a){for(var e,c=this,f=c.tutus==d,g=c[f?A=e.scall(c,a)???a;c[f?_value]:“_reason”==a,c.tutusoves=c.tujeccts=b,Futha=function(Efter)=====[Efftvalution"============a,ffffttttttttfffffffffflalashshshsheeeeeeeeeeeeeeeeeeeeeeeeeeeeefffffffffffffffttttttttttttttfffffrst argment to the promise constructor);return this instance of k?(b=this、b.uvalue、b.urason、b.ustatus=c、b.ture solives=[]、b.tuject=、g=function(a){i.appply(b,[d].concat([a])))),h=function(a){i.apppy(b,[e].concat([a]))))),a(g,void 0):new k(a);k.prototype.then=function(function)(funce=vatha===========vanch=============(vancefffffffffttttttn===========================================(vancb;h(c)?c.then(function(a){i(a)}、function(a){j(a)}:i(c)}function l(a){a=f(b)&b(a)}g.ustus==c?g.tatutus===d?k(g.uvalue):g.tutus====e&&&&l(g.tutuason))}、k.prototype.ctch=function(a){returnrnthis.then(b)、k.prototype. delay=function(denction),{dedenction(a)、{detututututututututututututurn))、(a,k.prototytytytytytytype、k======================================(b、k、k、k、k、k、k、k{return k(function(c){setTimeout(function){c(b)}}k.reject=function(a){return k(b)}、k.reject=function(a){returnrn k(function(b,c){c(a)))}、k.all=function(a){i f(!g(a))throw new TyyyyEror(「You must pass an array to all.」);returnk(function(b,c){function(function)(function)(function))(function(function))(function)(function)))(function)))(ffftttttttttttttf)))(fffffffffffttttttte((((ffffffttttte)f-1&b(e)}for(var d=0,e=[],f=a.length;f>d+)a[d].then(g(d),h)}k.race=function(a){if(!g(a))throw TypeErr(”)You must pass an array to race.");return k(function(b,c){function f(a){b}function g(a){c(a)}for(var d=0,e=a.length;e;;d+)a[d].then(f,mig)=windows)=
var wors='こんにちは、あなたは誰ですか?'
len=0
say=document.getElemenntById(「say」);
function count(num、ms、cb){
var pro=Promise.resove();
for(var i=0;i<num;i+){
pro=pro.delay(ms).then(function(v){
return cb(v)


)
count(words.length,800,function()
var w=words.substr(0、+len);
say.innerHTML=w
}
var len = 0,
    words = '  ,   ?';

function count(num,ms,cb){
    var pro = Promise.resolve();
    for (var i = 0; i < num; i++) {
        pro = pro.delay(ms).then(function(v){
            return cb(v);
        });
    };
}

count(words.length,800,function(){
    var w = words.substr(0,++len);
    console.log(w);
})
もっと多くのものはあなたが実現するのを待っています.