【深入淺出ES6】非同步Promise

Eric_zhang發表於2019-03-04

【深入淺出ES6】非同步Promise

Promise與非同步程式設計

建立一個待執行狀態的Promise

new Promise()會立即執行,因此如果需要在合適的位置建立Promise,可以使用一個函式進行包裝,合適的位置進行呼叫

let fs = require('fs')
function readFile(fileName){
    return new Promise((resolve, reject) => {
        //非同步操作
        fs.readFile(fileName, (err, contents)=> {
            //讀取錯誤時
            if(err){
                reject(err)
                return;
            }
            //讀取成功時
            resolve(contents)
        })
    })
}
let file = readFile('readme.txt')
// 同時監聽成功或失敗
file.then(data =>{

},err=>{

})
複製程式碼

直接返回一個已執行狀態的Promise物件

Promise.resolve()
Promise.reject()
複製程式碼
  • 傳遞給Promise.resolve()的引數,如果是一個Promise物件,則會原樣返回,如果不是一個Promise物件,針對非Promise的thenable物件,會做進一步包裝,將其轉換成Promise物件再返回(基本型別的值也會被自動轉換成Promise物件)
  • 非Promise的thenable物件:具有接受resolve、reject引數的then()方法的物件
    let thenable = {
        then(resolve,reject){
            console.log('enter thenable')
            resolve(42)
        }
    }
    let p1 = Promise.resolve(thenable)
    console.log('before then')
    p1.then(data =>{
        console.log(data)
    }).catch(err => {
        console.log(err)
    })
    /*
    before then
    enter thenable
    42
    */
    複製程式碼
    上例中 1.程式按順序執行,遇到Promise.resolve(thenable)時會把thenable中的then()中的非同步函式放入microtask佇列中,等主程式執行完後呼叫 2. 執行console.log('before then') 3. 執行p1.then()這裡,監聽p1的狀態,一旦由pending變為resolve或reject,便將其放入microtask佇列中,在主程式執行完後執行 4. 因此先列印before then,然後再列印enter thenable,最後是42

then()、catch()執行完後都會返回一個Promise物件,如果沒有顯式指定return,則會返回一個預設的Promise

響應多個Promise

  1. Promise.all([, , ,])引數是一個可迭代的物件(常用陣列),每個元素都是Promise物件

    let p1 = new Promise((resolve, reject) => {
        resolve('p1')
    })
    let p2 = new Promise((resolve, reject) => {
        resolve('p2')
    })
    let p3 = new Promise((resolve, reject) => {
        resolve('p3')
    })
    let p4 = Promise.all([p1, p2, p3])
    p4.then(value => {
        console.log(Array.isArray(value)) //true
        console.log(value) //["p1", "p2", "p3"]
    })
    複製程式碼

    Promise.all([]).then()then()中的引數是一個陣列,成員是你傳入的多個Promise物件中resolve的值

    let p1 = new Promise((resolve, reject) => {
        resolve('p1')
    })
    let p2 = new Promise((resolve, reject) => {
        reject('p2')
    })
    let p3 = new Promise((resolve, reject) => {
        resolve('p3')
    })
    let p4 = Promise.all([p1, p2, p3])
    p4.then(value => {
        console.log(Array.isArray(value)) //true
        console.log(value) //["p1", "p2", "p3"]
    }).catch(err => {
         console.log('err',err)
         }
     )
    複製程式碼

    如果Promise物件中觸發reject狀態,則會立即觸發Promise.all([]).catch()catch()中的引數是觸發reject()返回的值

  2. Promise.race([, , ,]) 多個Promise物件競賽,誰先觸發狀態變化,立刻停止

    let p1 = new Promise((resolve, reject) => {
        resolve('p1')
    })
     let p2 = Promise.resolve('p2')
     let p3 = new Promise((resolve, reject) => {
         resolve('p3')
     })
     let p4 = Promise.race([p1, p2, p3])
     p4.then(value => {
         console.log(value) 
     }).catch(err => {
     console.log('err',err)
     })
     // p1
    複製程式碼

相關文章