非同步解決方案---promise

シ皜彽調_N!發表於2019-02-05

為什麼需要promise

  • 回撥地獄 如果多個非同步請求 有連帶關係 回撥巢狀
  • 多個非同步實現併發的話,會出現無法同步非同步的返回結果
  • 錯誤處理不方便

什麼是promise(承諾)

  • promise 有三個狀態 (成功態 Resolved 失敗態 Rejected 等待態 Pending)
  • 預設情況下 狀態轉換(狀態不可逆)
    • pending -> resolved
    • pending -> rejected
    • resolved 不能和rejected相互轉換
  • 用法:promise在ie下是不相容的(可以使用webpack的polyfill等方式解決)
    // new Promise的時候 需要傳遞一個executor執行器,執行器函式會預設被內部所執行
    new Promise(function(resolve,reject){
        // 如果在這裡呼叫了resolve  就會變成成功態
        console.log('hello')   // 第一個執行
    })
    
    console.log('hello1') // 第二個執行
複製程式碼
    let p = new Promise(function(resolve.reject){
        resolve();
    })
    // 每個promise(例項)都有一個then方法
    // then方法是一個非同步方法,預設不會再當前的上下文中執行(微任務)且比setTimeout先執行
    p.then(function(){
        console.log('成功')
    },function(){
        console.log('失敗')
    })
複製程式碼
    // 面試題
    setTimeout(function(){
        console.log(1)
    },0)
    new Promise(function(resolve){
        console.log(2)
        for(var i = 0;i<10;i++){
            i==9 && resolve()
        }
        console.log(3)
    }).then(function(){
        console.log(4)
    })
    console.log(5)
    
    // 2 3 5 4 1
複製程式碼

promise解決非同步的基本使用

  • promise 每次呼叫then後,分下面幾種情況
    • 如果返回的是promise 用promise的成功或者失敗 執行下一個then
    • 如果返回的是一個普通值(包括不寫return,預設return undefined)會走外層下一個then的成功
    • 如果執行的時候,丟擲異常就會走到下一個then中的失敗
    • then中可以不傳遞引數,如果不傳遞 會透到下一個then中
  • catch用來捕獲錯誤的,相當於then的第一個引數傳遞null catch之後仍然可以繼續then
   let fs = require('fs')  
   
   function read(file){
       return new Promise(function(resolve,reject){
           fs.readFile(file,'utf8',function(err,data){
               if(err) reject(err)
               resolve(data)
           })
        })
   }
   // promise的鏈式呼叫
   read('./name.txt').then(function(data){
       // then方法成功後 返回的是一個新的promise 這個返回的promise會被執行,如果返回的promise是成功的,會把這個結果傳遞到外層的下一個then中    
        // return read(data)  返回下一個then成功
        // throw new Error('出錯了')  返回下一個then失敗
        return data  // 返回下一個then成功
   },function(err){
       console.log(err)
   }).then(function(data){
       console.log('age',data)
   }).then().catch(function(err){
       console.log('error',err)
   }).then(function(data){
       console.log(data)
   })
複製程式碼
    // 面試題
    new Promise(function(resolve,reject){
        resolve(1)
    })
    .then(function(data){
        console.log(data)
        return 2;
    })
    .catch(function(err){
        return 3;
    })
    .then(function(res){
        console.log(res)
    })
    // 1 2
複製程式碼

Promise.all(promise提供了一個 併發的方法 Promise.all 返回的結果是一個promise,只有傳遞的promise陣列全部成功才會返回成功態)

   Promise.all([read('./name.txt'),read('./age.txt')]).then(function(data){
        console.log(data)
    }).catch(function(err){
        console.log(err)
    }) 
複製程式碼

Promise.race(只要有一個返回成功 就返回成功態)

   Promise.race([read('./name.txt'),read('./age.txt')]).then(function(data){
        console.log(data)
    }).catch(function(err){
        console.log(err)
    }) 
複製程式碼

相關文章