簡單聊聊ES6-Promise和Async


前言

本篇博文出至於我的github倉庫:web-study,如果你覺得對你有幫助歡迎star,你們的點贊是我持續更新的動力,謝謝!

異步編程在前端開發中尤為常見,從最早的XHR,到后來的各種封裝ajax,再到DOM事件觸發的回調,無不涉及異步編程。今天咱們來聊聊ES6中新提出的異步解決方案:Promiseasync/await

  • Promise的原理和基本用法
  1. Promise的原理

Promise 是一種對異步操作的封裝,可以通過獨立的接口添加在異步操作執行成功、失敗時執行的方法。主流的規范是 Promises/A+。

Promise中有幾個狀態:

  * pending: 初始狀態, 非 fulfilled 或 rejected;

  * fulfilled: 成功的操作,為表述方便,fulfilled 使用 resolved 代替;

  * rejected: 失敗的操作。

node演示

pending可以轉化為fulfilled或rejected並且只能轉化一次,也就是說如果pending轉化到fulfilled狀態,那么就不能再轉化到rejected。並且fulfilled和rejected狀態只能由pending轉化而來,兩者之間不能互相轉換。

  1. Promise的基本用法

Promise是一個構造函數,自己身上有all、reject、resolve這幾個眼熟的方法,原型上有then、catch等同樣很眼熟的方法。

  • resolve的用法

    var p = new Promise(function(resolve, reject){
      //做一些異步操作
      setTimeout(function(){
          resolve('隨便什么數據');
      }, 2000);
    })
    p.then(res => {
      console.log(res) // '隨便什么數據'
    })
    

Promise的構造函數接收一個參數,是函數,並且傳入兩個參數:resolve,reject,分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。其實這里用“成功”和“失敗”來描述並不准確,按照標准來講,resolve是將Promise的狀態置為fullfiled,reject是將Promise的狀態置為rejected。

在上面的代碼中,我們執行了一個異步操作,也就是setTimeout,2秒后,並且調用resolve方法,表示異步操作執行成功。

  • reject的用法
    var p = new Promise(function(resolve, reject){
      //做一些異步操作
      setTimeout(function(){
          reject('隨便什么數據');
      }, 2000);
    })
    p.catch(err => {
      console.log(err) // '隨便什么數據'
    })
    ```

上面我們在異步操作中調用了`reject`方法,也就是說把Promise的狀態由`pending`轉換到了`fulfilled`狀態,最后可以通過Promise實例對象的`catch()`方法獲取異步數據。


* Async/Await簡介與用法

異步操作是 JavaScript 編程的麻煩事,很多人認為async函數是異步操作的終極解決方案。

1. Async/Await簡介

* async/await是寫異步代碼的新方式,優於回調函數和Promise。

* async/await是基於Promise實現的,它不能用於普通的回調函數。

* async/await與Promise一樣,是非阻塞的。

* async/await使得異步代碼看起來像同步代碼,再也沒有回調函數。但是改變不了JS單線程、異步的本質。

2. Async/Await的用法

* 使用await,函數必須用async標識

* await后面跟的是一個Promise實例或者是其他的任意js表達式(意義不大)

```javascript

var fun = async () => {
let result = await Promise.resolve(123)
console.log(result)
}
fun() // 123

await等待的雖然是promise對象,但是不用調用.then()方法就能直接得到返回值。

  1. Async/Await的應用

Promise雖然一方面解決了callback的回調地獄,但是相對的把回調“縱向發展”了,形成了一個回調鏈。example:

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

/*
let p1 = sleep(100)
let p2 = sleep(200)
let p =*/

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)
    //上一個await執行之后才會執行下一句
    let result02 = await sleep(result01 + 100)
    let result03 = await sleep(result02 + 100)
    // console.log(result03);
    return result03
}

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

因為async返回的也是promise對象,所以用then接受就行了。

結果:
300

需要注意的就是 await是強制把異步變成了同步,這一句代碼執行完,才會執行下一句。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM