我們的網易雲音樂系列內容,尾聲了,今天我們要將一個最重要的東西--關於ES7 async結合Fetch非同步編程問題。

ES7 async/await被稱作非同步編程的終極解決方案,我們先不管這個稱呼,咱們先總結一下,過去5次分享我們一路走來非同步編程是如何產生,到最後如何解決的。

第一次分享我們學會了切圖和動態計算響應式rem布局,第二次分享我們體會了如何學習使用原生js進行學習輪播圖,第三次分享了H5 audio這塊,進而引出了第四次的非同步請求歌詞ajax和第五次的Fetch+promise解決方案。

但是每一種方案都不完美,我們通過代碼來說明。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width_=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
var a = 12;
//模擬數據交互需要等1秒鐘
function loadData() {
setTimeout(function () {
a = 666;
}, 1000)
}
loadData();
console.log(a);
</script>
</head>
?
<body>
?
</body>
?
</html>

不用想,這個結果就是 12 而不是666,因為程序不會等1s才往下執行,但是有時候又必須使用數據,所以只能嵌套。但是嵌套多了又會出現下面的問題,案例來自SF的朋友,特此感謝。

?
<!DOCTYPE html>
<html lang="en">
?
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width_=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
setTimeout(function () {
console.log("第一個非同步回調了!")
setTimeout(function () {
console.log("第二個非同步回調了!")
setTimeout(function () {
console.log("第三個非同步回調了!")
setTimeout(function () {
console.log("第四個非同步回調了!")
setTimeout(function () {
console.log("第五個非同步回調了!")
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}, 1000);
</script>
</head>
?
<body>
?
</body>
?
</html>

我特意寫了一個程序,這下大家就能體會他的缺陷。

那我們怎麼解決呢?

<!DOCTYPE html>
<html lang="en">
?
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width_=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, "finish");
});
}
timeout(2000)
.then(value => {
console.log("第一層" + value);
return timeout(2000);
})
.then(value => {
console.log("第二層" + value);
return timeout(2000);
})
.then(value => {
console.log("第三層" + value);
return timeout(2000);
})
.then(value => {
console.log("第四層" + value);
return timeout(2000);
})
.then(value => {
console.log("第五層" + value);
return timeout(2000);
})
.catch(err => {
console.log(err);
});
</script>
</head>
?
<body>
?
</body>
?
</html>

Promise改成了鏈式,但是不夠完美,重點來了,今天的知識如何使用ES7 的async和await 讓我們跟我們寫日常普通代碼一樣寫非同步代碼呢?

大家發現了吧,這樣寫是不是正確並且簡單了啊,僅僅是加了兩個單詞而已,完整代碼

<!DOCTYPE html>
<html lang="en">
?
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width_=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, "finish");
});
}
async function asyncTimeSys() {
await timeout(1000);
console.log("第一層非同步結束!")
await timeout(1000);
console.log("第二層非同步結束!")
await timeout(1000);
console.log("第三層非同步結束!")
await timeout(1000);
console.log("第四層非同步結束!")
await timeout(1000);
console.log("第五層非同步結束!")
return "all finish";
}
asyncTimeSys().then((value) => {
console.log(value);
});
</script>
</head>
?
<body>
?
</body>
?
</html>

好,我們不整沒用的我們看看實際項目裡面怎麼搞的,還是拿網易雲舉例:

ok,感覺天都亮了。

簡單吧,通過這個系列課程的學習大家已經完整的了解了一個項目的大體開發過程,同時也了解了一些容易出錯的方方面面,重點是涵蓋了ES6和ES7的新知識。

當然,完全靠我講大家體會不深,還是希望大家能夠真的自己認真練習,把這個項目做出來,而不是變成聽聽而已。

本系列內容就到這,歡迎有問題想交流的同學,或者有專門技能提升需求的同學,在留言區里互相交流。

推薦閱讀:

相关文章