<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手寫 Promise

          共 7063字,需瀏覽 15分鐘

           ·

          2021-02-17 12:35

          作者:Waxiangyu
          來源:SegmentFault 思否社區(qū)




          Promise 的用法 :


          let?p?=?new?Promise(function(resolve,?reject){
          ????console.log(111)
          ????setTimeout(function(){
          ????????resolve(2)
          ????},?1000)
          })
          p.then(function(res){
          ????console.log('suc',res)
          },function(err){
          ????console.log('err',err)
          })


          可以看到new了一個Promise,里面有一個回調(diào)函數(shù),回調(diào)函數(shù)里有2個參數(shù),分別又是另外2個函數(shù)。其實里面很多也都是回調(diào)函數(shù)的封裝調(diào)用。


          const?[PENDING,RESOLVED,REJECTED]=["PENDING","RESOLVED","REJECTED"];`

          class?Promise1?{
          ????
          ????constructor(executor){
          ????????state?=?PENDING;
          ????????value?=?undefined;
          ????????reason?=?undefined;
          ????????
          ????????resolve?=?(value)?=>?{
          ????????????if(this.state?===?PENDING){
          ????????????????this.state?=?RESOLVED;
          ????????????????this.value?=?value;
          ????????????}
          ????????}
          ????????reject?=?(reason)?=>?{
          ????????????if(this.state?===?PENDING){
          ????????????????this.state?=?REJECTED;
          ????????????????this.value?=?reason;
          ????????????}
          ????????}
          ????????
          ????????try{
          ????????????executor(this.resolve,this.reject)
          ????????}catch(e){
          ????????????reject(e)
          ????????}
          ????}
          ?}


          測試一下執(zhí)行情況:


          let?p1?=?new?Promise1((resolve,reject)=>{//function:executor
          ????console.log(111)
          ????setTimeout(()=>{
          ????????resolve(111)//this.resolve,直接傳參調(diào)用
          ????},?1000)
          })


          下面就是 then 了


          class?Promise1?{
          ????constructor(executor){
          ????????...
          ????????onResolvedCallbacks=[];?//then,pending里先存起來
          ????????onRejectedCallbacks=[];

          ????????...

          ????????resolve?=?(value)?=>?{
          ????????????if(this.state?===?PENDING){
          ????????????????...
          ????????????????//executor里如果是異步會把then里存起來,然后executor走完了resolved的話,會再調(diào)then里回調(diào)函數(shù)
          ????????????????this.onResolvedCallbacks.forEach(fn?=>?fn(value))
          ????????????}
          ????????}
          ????????reject?=?(reason)?=>?{
          ????????????if(this.state?===?PENDING){
          ????????????????...
          ???????????????this.onRejectedCallbacks.forEach(fn?=>?fn(reason))
          ????????????}
          ????????}
          ????}
          ????
          ????then(onResolved,onRejected){
          ????????onResolved?=?typeof?onResolved?===?'function'???onResolved?:?value?=>?value;
          ????????onRejected?=?typeof?onRejected?===?'function'???onRejected?:?reason?=>?{
          ????????????throw?reason
          ????????};
          ????????
          ????????switch(this.state){
          ????????????case?RESOLVED?:?//狀態(tài)變了,就直接把結(jié)果給出去
          ????????????????onResolved(this.value);
          ????????????case?REJECTED?:
          ????????????????onRejected(this.reason);
          ????????????case?PENDING?:?
          ????????????//如果是pending的話,說明executor還沒走完,先存起來,走完再調(diào)用
          ????????????????this.onResolvedCallbacks.push(onResolved);
          ????????????????this.onRejectedCallbacks.push(onRejected)
          ????????}
          ????}
          }


          測試一下 :


          let?p2?=?new?Promise1((resolve,?reject)?=>?{
          ????setTimeout(()=>{
          ????????resolve(222)
          ????},?1000)
          })
          p2.then(res?=>?console.log(res,?'res'))?//222


          鏈?zhǔn)秸{(diào)用:


          class?Promise1?{
          ????...
          ????
          ????
          ????then(onResolved,onRejected){
          ????????...
          ????????//返回一個promise1
          ????????let?newPromise=new?Promise1((resolve,reject)=>{
          ????????????switch(this.state){
          ????????????????case?RESOLVED?:?//狀態(tài)變了,就直接把結(jié)果給出去
          ????????????????????setTimeout(()=>{//then,放后面處理
          ????????????????????????try{
          ????????????????????????let?reValue=onResolved(this.value);
          ?rePromise(newPromise,reValue,resolve,reject)
          ????????????????????????}catch(e){reject(e)}
          ????????????????????},0)
          ????????????????????
          ????????????????case?REJECTED?:
          ????????????????????setTimeout(()=>{
          ????????????????????????try{
          ????????????????????????????let?reValue=onRejected(this.reason);
          ????????????????????????????rePromise(newPromise,reValue,resolve,reject)
          ????????????????????????}catch(e){reject(e)}
          ????????????????????},0)
          ????????????????????
          ????????????????case?PENDING?:?
          ????????????????//如果是pending的話,說明executor還沒走完,先存起來,走完再調(diào)用
          ????????????????????this.onResolvedCallbacks.push(()=>{
          ????????????????????????setTimeout(()=>{
          ????????????????????????????try{
          ????????????????????????????????let?reValue=onResolved(this.value);
          ?rePromise(newPromise,reValue,resolve,reject)
          ????????????????????????????}catch(e){reject(e)}
          ????????????????????????},0)
          ????????????????????});
          ????????????????????this.onRejectedCallbacks.push(()=>{
          ????????????????????????setTimeout(()=>{
          ????????????????????????????try{
          ????????????????????????????????let?reValue=onRejected(this.reason);
          ????????????????????????????rePromise(newPromise,reValue,resolve,reject)
          ????????????????????????????}catch(e){reject(e)}
          ????????????????????????},0)
          ????????????????????})
          ????????????}
          ????????})
          ????????return?newPromise;
          ????}
          }

          //newPromise:新的promise1對象,reValue:上一個then的返回值,newPromise.resolve,newPromise.reject
          function?rePromise(newPromise,reValue,resolve,reject){
          ????//相當(dāng)于把自己return出去了,let?p2?=?p.then(res?=>?p2);
          ????if(newPromise?===?reValue){
          ????????reject(new?TypeError('循環(huán)了'))
          ????}
          ????if(reValue?!==?null?&&?(typeof?reValue?===?'object'?||?typeof?reValue?===?'function')){
          ????????try{
          ????//判斷一下reValue是不是promise1,是個對象,還帶有then函數(shù)
          ????//如果有then并是個函數(shù),就調(diào)then;?
          ????????????let?then?=?reValue.then;
          ????????????if(typeof?then?===?'function'){
          ????????????????then.call(reValue,?res=>{
          ????????????????????resolve(res)
          ????????????????},err=>{
          ????????????????????reject(err)
          ????????????????})
          ????????????}else{//then不是函數(shù),直接用resolve返回值
          ????????????????resolve(reValue)
          ????????????}
          ????????}catch(e){
          ????????????reject(e)
          ????????}
          ????}else{//只是個普通值
          ????????resolve(reValue)
          ????}
          }


          測試一下:


          p3.then(res?=>?{
          ????console.log(res)
          ????return?new?Promise1((resolve,?reject)?=>?{
          ????????resolve('p3')
          ????})
          }).then(res?=>?console.log(res,?'pp3'))//p3


          但還有個問題


          ...

          function?rePromise(newPromise,reValue,resolve,reject){
          ????...
          ????let?called;//是否調(diào)用過,防止多次調(diào)用
          ????if(reValue?!==?null?&&?(typeof?reValue?===?'object'?||?typeof?reValue?===?'function')){
          ????????try{
          ???
          ????????????let?then?=?reValue.then;
          ????????????if(typeof?then?===?'function'){
          ????????????????then.call(reValue,?res=>{
          ????????????????????if(called)?return;
          ????????????????????called?=?true;
          ???????????????????//promise1就繼續(xù)下一個,直到then走完,變成普通的值?
          ???????????????????rePromise(newPromise,res,resolve,reject)
          ????????????????},err=>{
          ????????????????????if(called)?return;
          ????????????????????called?=?true;
          ????????????????????reject(err)
          ????????????????})
          ????????????}else{//then不是函數(shù),直接用resolve返回值
          ????????????????resolve(reValue)
          ????????????}
          ????????}catch(e){
          ????????????if(called)?return;
          ????????????called?=?true;
          ????????????reject(e)
          ????????}
          ????}else{//只是個普通值
          ????????resolve(reValue)
          ????}
          }


          測試一下


          let?p1=new?Promise1((resolve,reject)=>{
          ????????resolve(111)
          ????})
          ????let?p2=p1.then(res=>{console.log(res,'p1')},err=>console.log(err,'p1'));
          ????p2.then(res=>console.log(res,'p2'))
          ????.then(res=>console.log(res,'p3))


          還有其它屬性:


          class?Promise1?{
          ????...
          ????catch(onReject){
          ????????return?this.then(null,onReject)
          ????}
          ????defer(){
          ????????let?defer={};
          ????????defer.promise=new?Promise1((resolve,reject)=>{
          ????????????defer.resolve=resolve;
          ????????????defer.reject=reject;
          ????????})
          ????????return?defer;
          ????}
          ????deffered(){
          ????????return?this.defer;
          ????}
          ????all(promises){
          ????????return?new?Promise1((resolve,reject)=>{
          ????????????let?done=gen(promises.length,resolve);
          ????????????for(let?i=0;i????????????????promises[i].then(res=>{
          ????????????????????done(i,res)
          ????????????????},reject)
          ????????????}
          ????????})
          ????}




          點擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復(fù)“?入群?”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          -?END -


          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美.www| 日韩在线中文字幕 | 成人理论视频三区 | 逼逼网站 | 日本特黄A片 |