天天看點

Promise練習題由易到難

1. 

Promise.resolve().then(()=>{
         return new Error('error!')
       }).then((res)=>{
         console.log('then: ',res)-----輸出的是這裡的
       }).catch((err)=>{
         console.log('catch:',err)
       })
           

輸出:

then:Error:error!

return了一個Error對象,然後被promise的鍊式調用傳下去了

2.

const promise=new Promise((resolve,reject)=>{
        resolve('success1');
        reject('error');
        resolve('success2');
      });
      promise.then((res)=>{
        console.log('then: ',res);
      }).catch((err)=>{
        console.log('catch: ',err);
      })
           

輸出:

then: success1

這道題就是考察Promise的狀态,一旦改變不能更改。第一個resolve将狀态從pending轉為fulfilled,然後将success1傳入.then的第一個函數,列印出來then: sucess1

3.

const promise=new Promise((resolve,reject)=>{
        console.log(1)
        resolve()
        console.log(2)
      });
      promise.then(()=>{
        console.log(3);
      })
      console.log(4);
           

輸出:

1

2

4

3

整個script是個宏任務,然後promise裡所有都是宏任務,console.log(4)也是同步任務,promise.then是微任務。執行第一個宏任務輸出1 ,将狀态pending轉為fulfilled,輸出2,輸出4,宏任務執行完,執行微任務,輸出3

4.

let p1=new Promise(function(resolve,reject){
         reject(42);
       });
       p1.catch(function(value){
         console.log(value);
         return value+1;
       }).then(function(value){
         console.log(value);
       });
           

輸出:

42

43

這裡p1.catch()可以看成是p1.then(function(){},function(err){})的簡寫,reject(42)将狀态從pending變為rejected,将參數42傳入value,輸出42,再通過鍊式調用将42+1傳入然後輸出43

5.

let p1=new Promise(function(resolve,reject){
         resolve(42);
       });
       let p2=new Promise(function(resolve,reject){
         reject(43);
       });
       p1.then(function(value){
         console.log(value);
         return p2;
       }).then(function(value){
         console.log(value);
       })
           

輸出:

42

這道題是考察狀态依賴。當存在狀态依賴,狀态由依賴項的狀态來決定。

一開始p1調用resolve()将狀态由pending變為fulfilled,然後調用p1.then的第一個函數,輸出42,但是第一個函數傳回p2依賴項,這時候p1自身的狀态無效,依賴p2的狀态。p2的狀态是rejected,是以p1的第二個.then不會執行了。

6.

setTimeout(()=>{
        console.log('timer1');
        Promise.resolve().then(()=>{
          console.log('promise1');
        })
      })
      Promise.resolve().then(()=>{
        console.log('promise2');
        setTimeout(()=>{
          console.log('timer2');
        })
      })
           

輸出:

promise2

timer1

promise1

timer2

setTimeout是宏任務,先注冊,而下面的Promise.resolve().then()是微任務,是以下面的優先執行。

然後先列印promise2,setTimeout是宏任務,之前先放入了第一個setTimeout,先執行第一個setTimeout。

輸出timer1,然後Promise.resolve().then是微任務,先執行微任務,輸出promise1

再執行宏任務輸出timer2

7.

Promise.resolve().then(()=>{
        Promise.resolve().then(()=>{
          console.log(1);
        }).then(()=>{
          console.log(2)//因為上面的.then沒有return 值,是以這裡的實際上是 
                        //Promise.resolve(undefined)
        });
      }).then(()=>{
        console.log(3);
      })
           

輸出:

1

3

2

首先最上面的Promise.resolve().then()是個微任務。

然後第二個Promise.resolve().then()和最後的.then()是同級的。一起被放入微任務隊列。先執行上面的微任務,是以先輸出1,然後把它的.then放入微任務隊列,執行隊列的下一個微任務,輸出3,再執行最後一個微任務,輸出2

8.

async function async1(){
         await async2();//這的傳回值一定是Promise,意味着往後走的一定是微任務
         console.log('async1 end');//當await傳回成功後才會執行它
       }
       async function async2(){
         console.log('async2 end');//傳回值undefined
       }
       async1();//同步任務
       console.log(10);//同步任務
           

輸出:

async2 end

10

async1 end

async1()函數執行,然後await asycn2(),但是async2裡面沒有用到異步,就是個普通的函數,加不加async都無所謂。也就是async2是個同步函數,先執行,輸出async2 end,但是await傳回值一定是Promise,意味着後面的那行console.log是微任務,接着往下執行同步任務,輸出10,輸出async1 end

9.

async function async1(){
         await async2();//這的傳回值一定是Promise,意味着往後走的一定是微任務
         console.log('async1 end');//當await傳回成功後才會執行它
       }
       async function async2(){
         console.log('async2 end');
         return Promise.reject();
       }
       async1();//同步任務
       console.log(10);//同步任務
           

輸出:

async2 end

10

10.

async function async1(){
         await async2();
         console.log('asycn1 ');
         await async3();
         console.log('async3');
      }
      async function async2(){
        console.log('async2 ');
      }
      async function async3(){
        setTimeout(()=>{
          console.log('async3 end');
        })
      }
      async1();
      console.log(10);
           

輸出:

async2

10

async1

async3

async3 end

執行async1()函數,await async2相當于同步代碼,執行async2,輸出async2,然後await接收Promise,成功。然後async1是微任務,先不管。然後執行外面的同步代碼輸出10。然後執行微任務輸出async1。執行await async3(),列印async3是微任務代碼,async3裡面的是宏任務代碼,微任務先執行,輸出async3,然後輸出async3 end

11.

console.log('start');

       async function async1(){
         await async2();
         console.log('async1 end');
       }

       async function async2(){
         console.log('async2 end');
       }

       async1();

       setTimeout(function(){
         console.log('setTimeout')
       })

       new Promise(resolve=>{
         console.log('Promise');
         resolve();
       }).then(()=>{
         console.log('promise1')
       }).then(()=>{
         console.log('promise2')
       })

       console.log('script end');
           

輸出:

start

async2 end

Promise

script end

async1 end

promise1

promise2

setTimeout

先找同步代碼,console.log('start')肯定最先執行。輸出start。然後執行async1()函數,一定執行await async2(),輸出同步任務async2 end。同步任務執行完了,然後接着往下看,先不管微任務async1 end,然後宏任務setTimeout不管,然後有個new Promise,是以new Promise内部是同步代碼,輸出Promise,然後注冊了成功的回調,2個。

再往下走,最後一個同步代碼,輸出script end。然後數微任務,輸出async1 end和.then()是微任務,是以輸出async1 end,然後輸出promise1,輸出promise2,最後宏任務輸出setTimeout

12.

console.log('start');

      async function async1(){
        await async2();
        console.log('async1 end');
      }

      async function async2(){
        console.log('async2 end');
        return Promise.reject(1);
      }

      async1();

      setTimeout(function(){
        console.log('setTimeout')
      })

      new Promise(resolve=>{
        console.log('Promise');
        resolve();
      }).then(()=>{
        console.log('promise1')
      }).then(()=>{
        console.log('promise2')
      })

      console.log('script end');
           

輸出:

start

async2 end

Promise

script end

promise1

promise2

setTimeout

13.

let a;

       const b=new Promise((resolve,reject)=>{
         console.log('promise1');
         resolve();
       }).then(()=>{
         console.log('promise2');
       }).then(()=>{
         console.log('promise3');
       }).then(()=>{
         console.log('promise4');
       })

       a=new Promise(async (resolve,reject)=>{
         console.log(a);
         await b;
         console.log(a);
         console.log('after1');
         await a;
         resolve(true);
         console.log('after2');
       });

       console.log('end');
           

輸出:

promise1

undefined

end

promise2

promise3

promise4

Promise{<pending>}

after1

new Promise,裡面第一句是同步代碼,輸出promise1,後面.then都是微任務,暫時不看。然後new Promise裡是個async函數。new Promise裡的代碼是同步代碼,是以輸出a是同步代碼。但是a還沒完成指派,是以輸出undefined。然後遇到await中斷,找後面的同步代碼,輸出end。再來看目前的微任務,三個.then是微任務。還有await b;b是Promise,await b的b是最後一個.then後的Promise。然後輸出promise2,promise3,promise4。然後await b是個成功态的Promise,此時同步任務全都執行完了,之前是因為沒執行完是以a沒指派,現在輸出a,a已經完成指派了。那麼a是個Promise對象,這裡a是個pending的狀态,輸出after1,await a。這裡還是pending。是以後面不會執行。

14.

async function async1() {
            console.log( 'async1 start' )
            await async2()
            console.log( 'async1 end' )
        }
        async function async2() {
            console.log( 'async2' )
        }
        console.log( 'script start' )
        setTimeout( function () {
            console.log( 'setTimeout' )
        }, 0 )
        async1();
        new Promise( function ( resolve ) {
            console.log( 'promise1' )
            resolve();
        } ).then( function () {
            console.log( 'promise2' )
        } )
        console.log( 'script end' )
           

輸出:

script start

async1 start

async2

promise1

script end

async1 end

promise2

setTimeout