1. 程式人生 > >簡談對ES7的async和await的理解

簡談對ES7的async和await的理解

如果遇到過深度回撥的朋友一定對JS的回撥地獄再熟悉不過了,舉個例子說(如果我的列子不恰當盡請諒解),常見的就是省市區級聯吧,假如我要獲取一個縣級市的資訊,那麼我首先得獲得它所在的省的資訊,當取得省的資訊以後,再拉去地級市的資訊,當獲得地級市的資訊以後,然後才有可能獲取到它的資訊。這就是典型的深度回撥的業務場景。這使得開發人員變得痛苦不堪,程式碼的質量難以得到保證。

對此,ES6中引入了一個Promise物件來解決此類問題(本文只做大概的講解),Promise,中文是諾言的意思,表示一段時間(pending)之後一定會獲得的結果(resolved狀態或者說是fullfilled狀態),當然有可能獲得的結果是錯誤的(rejected)。語法是:

function asyncReadFile() {
            return new Promise((resolve, reject) => {
                var counter = 0;
                var timer = setInterval(() => {
                    counter++;
                    console.log({
                        counter
                    })
                    if (counter >= 3) {
                        clearInterval(timer);
                        resolve('hello world');
                    }
                }, 1000)
            })
        }

然後我們通過asyncReadFile().then(result => {  console.log(result) }) 打印出hello world!。

對於之前的省市縣級聯的業務,我們可以利用Promise改寫成:

 getProvinces().then(result => {
            console.log('省級行政區域的資訊為:' + result)
            return getCities()
        }).then(result => {
            console.log('地級行政區域的資訊為:' + result)
            return getAreas()
        }).then(result => {
            console.log('縣級行政區域的資訊為:' + result)
        })

假設getProvince、getCities、getAreas都返回一個Promise物件,本來深度回撥的程式碼,就變成了序列的程式碼。(請大家避免如下書寫有關Promise的程式碼)

 getProvinces().then(result => {
            console.log('省級行政區域的資訊為:' + result)
            getCities().then(result => {
                console.log('地級行政區域的資訊為:' + result)
                getAreas().then(result => {
                    console.log('縣級行政區域的資訊為:' + result)
                })
            })
        })

雖然Promise解決了深度回撥的問題,但是卻引入了大量無用的程式碼,你會寫很多then,程式碼也變得很難看了。

於是,ES7中加入了async和await這對關鍵字。

await 命令只能用在async函式之中。async函式是基於Generator函式的實現,由於我們直接跳過了generator,這兒必須得提一個概念叫做協程,才便於大家對async函式的理解。就是函式在執行的時候,如果遇到一些條件,它會將執行條件交給另外的函式,等另外的函式執行完成之後,再將執行權力交回繼續執行。(純屬個人理解,如果紕漏,盡情指出)。

畫個圖就是如下:


async function asyncGetFileInfo() {   var fileInfo await getFileInfo();  return fileInfo; }

這段程式碼的意思正如上圖所示。async函式返回的是一個Promise,我們這樣來理解吧,裡面既然是非同步的東西,肯定有些東西要等一會兒才可以得到吧。而await(await緊跟一個Promise)直接是取得非同步的結果,我們可以不用再呼叫then。

然後 剛才那麼多Promise組成的獲得行政區域的資訊的方法可以簡化成如下程式碼:

async function getDistrictInfo() {
            var province = await getProvinces();
            var city = await getCities();
            var area = await getAreas();
            return `${province}省(市,自治區)${city}市(區)${area}縣市區旗`
        }

getDistrictInfo().then(result => {  console.log(result); });

由於ES7太新,瀏覽器支援的不太好(nodejs請放心使用),我們需要babel進行轉碼。

npm install --save-dev babel-preset-latest