教えてあげます.一歩ずつ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の使用は大体次の通りです.
ここの関数はすぐには実行されません.列に参加して、将来のある時間を待つときに実行されます.
以上の説明があれば、実現できます.
最初に3つの状態を定義します.
var PENDING=undefined、FUL FILLED=1、REJECTED=2
次にPromiseコンストラクタを実現します.この関数は関数パラメータを受け入れます.関数パラメータは私たちが提供する二つの方法を受け入れます.
使用者が将来のある時間に私たちのキューを実行するためにトリガを呼び出します.ここでは現在の状態、転送の値を初期化します.
およびthen時に保存されたキュー.
大体次のように
thenでやるべきことはプロミセを返してthenに送るチェーンコールです.
また、プロミゼ.then(オンフルフィlled、オンリージェクト)の場合は、現在のプロミスの状態を判断します.
pendingであればonFulfilledとonRejecedを_に追加します.reolvesと_reject配列には、
さもないと、状態によって、直接にフィードバックを触発します.ここで注意すべきことは、プロミセが戻ってきたら、私たちはこのプロミセがレレスされるまで待ちます.
thenチェーンの次のpromiseをトリガーして実行します.
コードは大体このようです.
var isThe nable=function(obj){return obj&typeof obj['then'='function';
つまり、戻ってきた相手はthen方法を持っています.私たちはpromiseの対象とします.
ここまで私達の主要な仕事は完成しました.他のall、raceなどの方法は全部簡単です.具体的にここに来て完全な実現を見ることができます.
https://github.com/ygm125/promise/blob/master/promise.js
いくつかの例を挙げて、効果を見てみましょう.
thenは一つだけ伝えてもいいです.成功したコールバックを受けてもいいです.catch方法で失敗のコールを受けてもいいです.
catchはthenのシンタックス飴で、promise.thenに相当します.
allで並行して実行することもできます.
私達も直接にobjを値とする成功状態のpromiseを作成できます.
ここでもいくつかの面白いものを作ることができます.例えばdelay方法を作ることです.
<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
}
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);
})
もっと多くのものはあなたが実現するのを待っています.