來自老曾es6的前言:
- 哈嘍小伙伴們,愛說‘廢’話的Z又回來了,歡迎來到Super IT曾的博客時間,上一節說了字串,面向物件以及json的知識,這一節我們繼續我們知識的海洋,一起奮斗不禿頭!不足的歡迎提問留言,

我發誓我真的沒有P圖??,沒想到這個系列被小編看上了,從發布這個系列起就都上熱門了,怪害羞的,哈哈讓人老臉一紅的既視感,既然如此!我會認真把這個系列做完的,然后帶你們搞專案搞框架!我們一起搞事情!那現在我們就開始吧!這一節是es6結局哦,下節就要說es789....的啦哈哈哈,

Promise
- 老曾英語教學開始,promise是什么,是承諾,我可是一言九鼎的人啊,別說四匹馬,四十匹馬都拉不回來我,那么解釋起來promise就是這件事我肯定會做,至于多久做嘛~反正肯定會做的對吧!那么promise和我們es6有什么關系呢?我們先賣個關子,
- 這里就要先提到兩個東西了,相信有一定基礎的小伙伴一定知道我想說啥,對就是異步和同步,
| 兩步 | 特點1 | 特點2 |
|---|---|---|
| 異步 | 操作之間沒啥關系,可同時進行多個操作 | 代碼更復雜 |
| 同步 | 同時只能做一件事 | 代碼簡單 |
那么你肯定又想問異步和同步專案中怎么應用的?我拿它來干嘛?我打個比方:

這里的圖片資料文字資料等等都不是寫死的吧,都需要從后臺去拿,如果你使用異步,這時候就好比這種代碼,也叫回呼地獄,這種好嚇人哦,要是上百條資料上千條那怎么遭得住,不知道你們遭得住不,反正我是遭不住,
//callback-hell 回呼地獄
getFileContent('a.json',data =https://www.cnblogs.com/Three-Z/p/> {
console.log("data",data)
getFileContent(data.next, data2 =>{
console.log('data2',data2)
getFileContent(data2.next, data3 =>{
console.log('data3',data3)
})
})
})
這個時候就要請出我們的Promise了,它的作用就是用來消除異步操作,它具體是怎么的呢?一句話概括:
- 用同步的方式,書寫異步的代碼
Promise到底怎么用
- 我們以一個ajax示例來看,你說你不知道ajax怎么辦,沒關系,你跟著看,以我對你的了解你看得懂哈哈,至少不影響代碼閱讀,跟著看了之后,回頭自己個兒再看一下ajax教程你就完全懂了,廢話暫時到這,先看目錄結構:



- 現在,問題來了,我要在index里面ajax請求這兩個json檔案,成功列印出里面json內容,失敗則彈出失敗,想想怎么做?提示一點,Promise.all的使用:

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
let p1 = new Promise((resolve, reject) =>{
//異步代碼
$.ajax({
url: 'dataA.text',
dataType: 'json',
success(arr) {
resolve(arr)
},
error(err) {
reject(err)
}
})
})
let p2 = new Promise((resolve, reject) =>{
$.ajax({
url: 'dataB.text',
dataType: 'json',
success(arr) {
resolve(arr)
},
error(err) {
reject(err)
}
})
})
Promise.all([
p1,p2
]).then((arr) =>{
let [resA,resB] = arr
alert("all success")
console.log(resA,resB)
},(err) =>{
alert("fails")
console.log(err)
})
</script>
光看代碼有沒有理解一點呢,別急代碼會繼續優化,我們先來決議代碼,使用箭頭函式和解構賦值的地方都是我們前面博客說過的咯,忘記的童鞋就自己翻看一下老曾之前的博文啦,當然我也是貼心大暖男,放圖來給你注釋決議:
- 有道翻譯 resolve--解決了,reject--拒絕了
- 那拿到我們這里就明明白白了,resolve成功,reject失敗
圖一,對應請求成功失敗的執行以及回傳:

- Promise對應成功失敗的執行以及回傳,綠字對綠框,紫字對紫框,紅字對紅框,順便一提,無論是請求或是什么,有失敗的函式一定要執行養成良好的習慣,我之前就不愛寫失敗的回傳,蜜汁自信有沒有哈哈哈,就會導致有時候不知道錯誤原因,

這樣我怕你還不知道p1,p2,我給你列印一下可好???畢竟自己的粉自己疼p1,p2,console的代碼中間有個逗號哈,只不過被線遮住了,看圖就發現是promise物件:

現在來簡化代碼,我說過,我是個懶人,雖說p1和p2直接ctrl c+ctrl v再改改一個字母代碼就好了,但我都懶得復制粘貼,兩大坨代碼看著就emm那啥,我們一個函式封裝一下嘛:
<script>
function createPromise(url){
return new Promise((resolve, reject) =>{
$.ajax({
url: url,
dataType: 'json',
success(arr) {
resolve(arr)
},
error(err) {
reject(err)
}
})
})
}
let p1 = createPromise("dataA.text")
let p2 = createPromise("dataB.text")
Promise.all([
p1,p2
]).then((arr) =>{
let [resA,resB] = arr
alert("all success")
console.log(resA,resB)
},(err) =>{
alert("fails")
console.log(err)
})
</script>
這樣就清爽的多了有沒有,當然這遠遠不夠,你還能像到更優化的嗎?不能的話就跟著來,看看代碼列印出啥?
let p = $.ajax({url:'dataA.text',dataTape:'json'})
console.log(p)

發現沒jQuery回傳的本身就有promise物件,所以我們不用自己用p1,p2接收一個promise,現在直接用就好了:
<script>
Promise.all([
$.ajax({url:"dataA.text",dataType:'json'}),
$.ajax({url:'dataB.text',dataTape:'json'})
]).then((arr) =>{
console.log("success",arr)
},(err) =>{
console.log('fail',err)
})
</script>
這樣是不是爽多了有沒有!!!!

- 這才是Promise的完美用法,Promise.all是必須全部成功才執行成功,更像‘與’有沒有,這里我們提一下另外一個,Promise.race,這個的話意思就是那個來了就先執行哪個,有一個成功都會執行成功的函式,
generator
generator的基本功能
- 這是個啥?英語不好不存在哇搜一搜,翻譯過來就是生成器,那這個有啥用?通俗易懂的來對比一下,
- 普通函式:一路到底 —— 高鐵火車
- generator函式:隨叫隨停 —— 出租車
那么我們就來看看這個generator和普通函式有啥不同?瞅瞅看列印出來是啥?猜猜?說實話我最開始也不知道哈哈哈??,這里提示一下yield翻譯過來是放棄的意思,我們這里把他理解為暫時放棄,
<script>
function *show(){
alert('a');
yield;
alert('b')
}
show()
</script>
你是不是覺得會彈出一個a,沒想到吧,啥也沒有,控制臺也不報錯,這時候咋辦呢?alert(show()),同時console.log(show())一下,查看一下呢?

alert出來的倒沒啥,就告訴你執行出來是個生成器物件,但是當我們看他里面的時候就會發現里面有一個next方法,這個就很重要了,

那我們就來show().next();執行一下看看是個啥?

那如果既要顯示a又要顯示b呢?我們試試這樣寫:
let obj = show()
obj.next();
obj.next();

這樣a,b就都出來了,這里只放了b,所以next給人的感覺就是踹一步走一下的感覺對吧,那你要問老曾老曾這個generator的原理是怎么實作走走停停的呢?你猜我給你說不說哈哈,當然要說,
- generator的基本原理在這里就是把原來的*show()函式劃分為了兩個小函式,當然你是看不見的,這里就相當于劃分為了show1和show2,各自執行alert('a')和alert('b'),
細說yield
yield傳參
- 上一個小點我們剛說了,yield是暫時放棄的意思,同時也對Promise有了一個基本的了解,那來看看這段代碼你能猜對執行結果嘛?
<script>
function *show(){
alert('a');
let a = yield;
alert('b');
alert(a);
}
let gen = show();
gen.next(12);
gen.next(5);
</script>


注意重點來了!

5???有沒有懷疑人生?哈哈我很懵逼啊表示,來來來我們來分析一下兩個next分別執行的是*show的哪兩段代碼:

第一次next是不是應該是白框框的代碼,碰到yield暫停了嘛,第二次next就是黃框框的代碼,所以gen.next(5);是給誰傳遞的值,看黃框框,是不是就是給let a傳遞的值,這樣不難理解吧,
- 那你說如果想給上面白框框alert值怎么辦?
function *show(num1,num2){
alert(`${num1} ${num2}`)
alert('a');
let a = yield;
alert('b');
alert(a);
}
let gen = show(9,99);
gen.next(12);
gen.next(5);

這樣就可以了嘛,所以也可以看出第一個next對于yield傳參是廢的,是沒有用的好吧,
yield回傳
*來來來,yield傳參玩完了我們來說說回傳,一樣一樣來猜猜代碼執行結果是什么?
<script>
function *show(){
alert('a');
yield 12;
alert('b');
return 55;
}
let gen = show();
let res1 = gen.next();
console.log(res1)
let res2 = gen.next();
console.log(res2)
</script>



相信機智的你至少已經看出來了一點,這里的done就是是否執行完畢,那按照之前白框框和黃框框的理解,回傳value是12和55能理解嗎?還不能理解的話我們就來繼續看~
yield到底是個啥
- 這里咱就不搞代碼了,咱來搞一個接地氣的偽代碼,你來品品:

說白了就像是一個廚房的分工以yield隔開,各做各的事情,就這么簡單,還不懂得小伙伴評論區留言哦~
generator的實體
- 介紹完了generator也了解了它的基本使用,那我們不是說它也可以用來消除異步操作嘛?那具體是怎么做的呢?
- 首先我們需要一個runner檔案,我會把它放在github上,文章末尾有github鏈接點進去在es6的15的檔案夾里就可以看到啦,沒找到檔案的可以私聊我??,

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script src="https://www.cnblogs.com/Three-Z/p/runner.js"></script>
<script>
runner(function *(){
let data1 = yield $.ajax({url:'dataA.text',dataType:'json'})
let data2 = yield $.ajax({url:'dataB.text',dataType:'json'})
let data3 = yield $.ajax({url:'dataC.text',dataType:'json'})
console.log(data1,data2,data3)
})
</script>
對應的dataA,B,C就有了,這里要注意一點就是我們第一個$.ajax回傳的promise回傳給了誰,我們這里其實回傳給了runner去處理然后yield暫停,處理完了后就會回到data1繼續執行,完了第二個ajax就會給data2,依次data3,

異步操作總結
回呼
//回呼
$.ajax({
url: xxx,
dataType: 'json'
success(data1){
$.ajax({
url: xxx,
dataType: 'json'
success(data2){
$.ajax({
url: xxx,
dataType: 'json'
success(data3){
//完事兒
},
error(){
alert('錯了');
}
});
},
error(){
alert('錯了');
}
});
},
error(){
alert('錯了');
}
});
Promise
//Promise
Promise.all([
$.ajax({url: xxx, dataType: 'json'}),
$.ajax({url: xxx, dataType: 'json'}),
$.ajax({url: xxx, dataType: 'json'})
]).then(results=>{
//完事兒
}, err=>{
alert('錯了');
});
generator
//generator
runner(function *(){
let data1=yield $.ajax({url: xxx, dataType: 'json'});
let data2=yield $.ajax({url: xxx, dataType: 'json'});
let data3=yield $.ajax({url: xxx, dataType: 'json'});
//完事兒
});
Promise的缺點
- 光看上面的11.2和11.3是不是感覺兩個差別不大,確實,但是如果promise帶邏輯,就比如一個用戶登錄了是vip怎么怎么樣,不是VIP又怎么怎么樣?這個時候我們的代碼是什么樣子的呢?
//帶邏輯-Promise
Promise.all([
$.ajax({url: 'getUserData', dataType: 'json'})
]).then(results=>{
let userData=https://www.cnblogs.com/Three-Z/p/results[0];
if(userData.type=='VIP'){
Promise.all([
$.ajax({url: 'getVIPItems', dataType: 'json'})
]).then(results=>{
let items=results[0];
//生成串列、顯示...
}, err=>{
alert('錯了');
});
}else{
Promise.all([
$.ajax({url: 'getItems', dataType: 'json'})
]).then(results=>{
let items=results[0];
//生成串列、顯示...
}, err=>{
alert('錯了');
});
}
}, err=>{
alert('失敗');
});
我的天一大堆,來看看普通回呼,這個時候說實話我還不如用普通回呼,
//帶邏輯-普通回呼
$.ajax({url: 'getUserData', dataType: 'json', success(userData){
if(userData.type=='VIP'){
$.ajax({url: 'getVIPItems', dataType: 'json', success(items){
//生成串列、顯示...
}, error(err){
alert('錯了');
}});
}else{
$.ajax({url: 'getItems', dataType: 'json', success(items){
//生成串列、顯示...
}, error(err){
alert('錯了');
}});
}
}, error(err){
alert('錯了');
}});
普通回呼都比Promise好對吧,但是有了generator,來看看它怎么寫?
//帶邏輯-generator
runner(function *(){
let userData=https://www.cnblogs.com/Three-Z/p/yield $.ajax({url:'getUserData', dataType: 'json'});
if(userData.type=='VIP'){
let items=yield $.ajax({url: 'getVIPItems', dataType: 'json'});
}else{
let items=yield $.ajax({url: 'getItems', dataType: 'json'});
}
//生成、...
});
這個時候是不是感覺他的優勢一下子就顯現出來了,就和我們平時的普通函式執行一樣,簡單粗暴,
好了到這里我們的ES6說的就差不多了!!!!!!!!四個系列終于說完,

———————————————————————分割線——————
都看到這里了,只能說明一點,咱倆真的真的真的很有緣分啊!不點個贊再走嘛,????,順手加個關注嘛,偷偷收藏我博文的小可愛我后臺看得到的嘛,點個贊給老曾支持支持,不出意外接下來我一直都在哈哈哈,學知識寫博客不著急,基礎打好,專案直接上手6到飛起,
下節說ES7,及之后版本的內容
放上我的,主要博客博客園,CSDN,GitHub,pipe
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/126423.html
標籤:JavaScript
