每日技術:Promise和Async/Await用法

 

Promise

Promise是一個容器,裏面保存着某個將來纔會結束的時間(一般是一個異步操做的結果)編程

Promise對象的基本語法:數組

let p = new Promise((resolve, reject) => {
    // ...
    resolve('success')
})

p.then(res => {
    console.log(res); // success
})

Promise對象特色和三個狀態:promise

  1. 對象的狀態不受外界影響
  2. 一旦狀態改變,就不會再變,狀態會被凝固。

例如:瀏覽器

let p = new Promise((resolve, reject) => {
    // ...
    resolve('success')
    console.log('after resolve')
    reject('error')
})

p.then(res => {
    console.log(res); // success
})

p.catch(err => {
    console.log(err)
})

// 運行結果:after resolve -> success

resolve下面的語句實際上是能夠執行的,那麼爲何reject的狀態信息在下面沒有接收到呢?這就是由於Promise對象的狀態凝固了。dom

new出一個Promise對象時,這個對象的起始狀態就是Pending狀態,再根據resolve或reject返回Fulfilled狀態/Rejected狀態。異步

Promise.prototype.then 的做用是爲Promise實例添加狀態改變時的回調函數。能夠有兩個參數async

  • .then(func1, func2)
  • .then(func1)
  • .then(null, func2)

Then分別接受resolve, reject的信息異步編程

let p = new Promise((resolve, reject) => {
    // ...
    let random = Math.random(); //小於1大於0
    if (random > 0.4) {
        resolve('random > 0.4');
    } else {
        reject('random <= 0.4');
    }
})

p.then(res => {
    console.log('resolve', res)
}, res => {
    console.log('reject', res)
})

 

Promise.resolve() 

Promise.resolve() 將現有對象轉爲Promise對象的快捷方式函數

let p1 = Promise.resolve({name: 'xixi', age: 18})

p1.then(result => {
    console.log(result)
})

若是是Promise對象,直接返回spa

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 500)
})

let pp = Promise.resolve(p)

pp.then(res => {
    console.log(res)
})

console.log(pp == p)

// 輸出結果:true -> success

 

Promise.reject() 

Promise.reject() 快速地獲取一個拒絕狀態的Promise對象

let p = Promise.reject(123)
console.log(p)

p.then((res) => {
    console.log(res)
}).catch(res => {
    console.log('catch', res)
})

// 輸出結果:Promise {<rejected> 123} -> catch 123

 

Promise.all()

let p1 = Promise.resolve(123);
let p2 = Promise.resolve('hello');
let p3 = Promise.resolve('success');

Promise.all([p1, p2, p3]).then(result => {
    console.log(result);
})

// 結果:[123, 'hello', 'success']

當全部的狀態都是成功狀態才返回數組,不然返回reject的狀態。

再來一個例子,用sleep模仿瀏覽器的AJAX請求

function sleep(wait) {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res(wait)
        }, wait)
    })
}

let p1 = sleep(500)
let p2 = sleep(500)
let p3 = sleep(1000)

Promise.all([p1, p2, p3]).then(result => {
    console.log(result)
    // ...
    // loading
})

 

Promise.race() 

Promise.race() 將多個Promise實例,包裝成一個新的Promise實例。哪一個對象返回的快就返回哪一個對象。race最終只有一個值。

 

 

Async-Await

簡介

異步編程的最高境界,就是根本不用關心它異步。

async函數就是隧道盡頭的亮光,不少人認爲它是異步操做的終極解決方案。

 

async-await與promise的關係

不存在誰替代誰的,由於async-await是寄生於Promise,Generator的語法糖

規則:

  1. async表示這是一個async函數,await只能用在這個函數裏面
  2. await表示在這裏等待promise返回結果後再繼續執行。
  3. await後面跟着的應該是一個promise對象

 

應用

Promise雖然一方面解決了callback回調地獄,可是相對的把回調「縱向發展」了,造成了一個回調鏈。

舉例:

function sleep(wait) {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res(wait)
        }, wait)
    })
}

sleep(100).then(result => {
    return sleep(result + 100)
}).then(result02 => {
    return sleep(result02 + 100)
}).then(result03 => {
    console.log(result03)
})

// 結果:300

後面的結果都是依賴前面的結果,改寫async/await寫法以下:

async function demo() {
    let result01 = await sleep(100)
    let result02 = await sleep(result01 + 100)
    let result03 = await sleep(result02 + 100)

    return result03
}

demo().then(result => {
    console.log(result)
})

// 結果:300

 

錯誤處理

既然.then()不用寫了,那麼catch()也不用寫了,能夠直接用標準的try catch語法捕捉錯誤

若是是reject狀態,能夠用try-catch捕捉

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('error')
    }, 1000)
})

async function demo(params) {
    try {
        let result = await p
    } catch(e) {
        console.log(e)
    }
}

demo()

 

注意你的並行執行和循環

await in for循環

await的執行上下文必須是async函數

若是在forEach或者map的循環裏使用await,這時候上下文就變成了array,而不是async function 就會報錯。

 

 

以上筆記摘自:https://www.jianshu.com/p/fe0159f8beb4

相關文章
相關標籤/搜索