Promise≠異步,async函數(shù)≠異步

本文并不提供Promiseasync函數(shù)的用法說明,僅嘗試通過簡單的示例代碼對(duì)Promiseasync函數(shù)的概念和本質(zhì)作簡單梳理。

Promiseasync函數(shù)是為異步而生侍咱,但是,如果將它們和異步劃等號(hào)密幔,可能就有問題了楔脯。
查看原文

先說Promise

定義 promise

// 定義 promise  
const promise = new Promise((resolve, reject) => {  
  console.log('promise start');  

  // 用一個(gè)for循環(huán)簡單模擬一下大數(shù)據(jù)量處理  
  for (let index = 0; index < 5; index++) {  
    console.log('promise process ' + index);    
  }  

  console.log('promise end');  
})  

console.log('1');  
// 按照慣例,then 一下  
promise.then(()=>{console.log('Promise done')});  
console.log('2');  

運(yùn)行結(jié)果:

promise start  
promise process 0  
promise process 1  
promise process 2  
promise process 3  
promise process 4  
promise end  
1  
2  

在這個(gè)示例代碼中胯甩,定義Promise的代碼在定義時(shí)就已經(jīng)同步執(zhí)行了昧廷,后面的then調(diào)用沒有任何輸出。
A:"說明什么蜡豹?說明Promise不是異步的,它的定義和執(zhí)行都不是異步的溉苛!"
B:“你胡說镜廉,你連resolve都沒用!”

加入resolve

const promise = new Promise((resolve, reject) => {  
  console.log('promise start');  

  for (let index = 0; index < 5; index++) {  
    console.log('promise process ' + index);    
  }  

  // 用resolve拋出一個(gè)值  
  resolve('promise done');  

  console.log('promise end');  
})  

console.log('1');  
// then 的回調(diào)函數(shù)中接到resolve拋出的值并輸出到控制臺(tái)  
promise.then((v)=>{console.log(v)});  
console.log('2');  

運(yùn)行結(jié)果:

promise start  
Promise0  
Promise1  
Promise2  
Promise3  
Promise4  
promise end  
1  
2  
promise done  

B:“異步了吧愚战?異步了吧娇唯?‘promise done’在2后面出來的齐遵。”
A:“整個(gè)promise執(zhí)行過程是同步的塔插,把返回值異步出來梗摇,頂個(gè)X用!”
B:"......"
B:"我想起來了想许,阮大俠說:“Promise只是個(gè)異步操作容器”伶授,所以你要在Promise中裝個(gè)異步操作進(jìn)去才行!"

塞個(gè)異步操作

const promise = new Promise((resolve, reject) => {  
  console.log('promise start');  

  // 這個(gè)setTimeout就是塞進(jìn)來的異步操作  
  setTimeout(()=>{  
    
    // 原來的大數(shù)據(jù)量處理語句移到setTimeout中來  
    for (let index = 0; index < 5; index++) {  
      console.log('Promise' + index);    
    }  

    // 原來的結(jié)果返回語句也移到setTimeout中來  
    resolve('promise done');  

  },1000);  
  
  console.log('promise end');  
})  

運(yùn)行結(jié)果:

promise start  
promise end  
1  
2  
Promise0  
Promise1  
Promise2  
Promise3  
Promise4  
promise done  

B:“異步了吧流纹?異步了吧糜烹?整個(gè)業(yè)務(wù)邏輯都是在2后面出來的∈”
A:“是異步了疮蹦,但是setTimeout本身就執(zhí)行了一個(gè)異步操作,干嘛要多此一舉的把它塞進(jìn)Promise里呢茸炒?”
B:“......”

為什么要用Promise

我們?cè)诋惒秸{(diào)用時(shí)經(jīng)常會(huì)遇到"后一個(gè)異步調(diào)用的參數(shù)是前一個(gè)異步調(diào)用的結(jié)果"的情況愕乎,傳統(tǒng)方式寫出來是這樣:

a(參數(shù),function(){  
  b(result-from-a,function(){  
    //.....  
  })  
})  

a和b嵌套起來了壁公,如果關(guān)聯(lián)關(guān)系更多感论,可能會(huì)出現(xiàn)這種情況:

a(參數(shù),function(){  
  b(result-from-a,function(){  
    c(result-from-b贮尖,function(){  
      d(result-from-c笛粘,function(){  
        e(result-from-d,function(){  
           //.....  
        })  
      })  
    })  
  })  
})  

這還只是非常理想的單一數(shù)據(jù)獲取情況下的嵌套湿硝,如果有分支嵌套再加上異常處理薪前,那干脆能亂成一鍋粥。這就是那個(gè)有名的“回調(diào)地獄”关斜。
怎么破示括?Promise!

a.then((result-from-a)=>{  
  return b(result-from-a);  
})  
.then((result-from-b)=>{  
  return c(result-from-b);  
})  
.then((result-from-c)=>{  
  return d(result-from-c);  
})  
.then((result-from-d)=>{  
  return e(result-from-d);  
})  
.then((result-from-e)=>{  
  console.log(result-from-e);  
})  
.catch((error)=>{  
  console.log(error);  
})  

這樣舒心多了吧?

所以痢畜,Promise是個(gè)包裝器垛膝,把異步操作包起來,以更易讀更有條理更符合人類思維習(xí)慣的方式讓廣大程序猿(嬡)來寫異步代碼丁稀。如果拋開異步操作使用Promise就是耍流氓。
要點(diǎn)是:Promise是用來包裝異步操作的

再看async函數(shù)

B:”async,就是異步的意思线衫,async函數(shù),當(dāng)然就是異步執(zhí)行的函數(shù)了。這個(gè)不存在二義性吧枯跑?“
A:”這個(gè)......,咱們用代碼說話......“

初探async函數(shù)

// 定義 async 函數(shù)  
async function asynFunction(){  
  console.log('asynFunction begin');  

  // 還是用一個(gè)for循環(huán)代表大數(shù)據(jù)量處理  
  for (let index = 0; index < 5; index++) {  
    console.log('asynFunction process ' + index);    
  }  

  console.log('asynFunction end');  
}  

console.log('1');  
// 調(diào)用 async 函數(shù)  
asynFunction();  
console.log('2');  

執(zhí)行結(jié)果:

1  
asynFunction begin  
asynFunction process 0  
asynFunction process 1  
asynFunction process 2  
asynFunction process 3  
asynFunction process 4  
asynFunction end  
2  

B:”這個(gè)......敛助,異步函數(shù)沒有異步執(zhí)行?會(huì)不會(huì)是什么地方寫錯(cuò)了纳击?“
A:”哈哈,加點(diǎn)東西給你看看“

await出場

async function asynFunction(){  
  console.log('asynFunction begin');  

  // 加入 await  
  await 'async go!';  

  for (let index = 0; index < 5; index++) {  
    console.log('asynFunction process ' + index);    
  }  

  console.log('asynFunction end');  
}  

console.log('1');  
// 調(diào)用 async 函數(shù)  
asynFunction();  
console.log('2');  

執(zhí)行結(jié)果:

1  
asynFunction begin  
2  
asynFunction process 0  
asynFunction process 1  
asynFunction process 2  
asynFunction process 3  
asynFunction process 4  
asynFunction end  

B:"從await開始评疗,后面語句都異步了?難道await表示異步開始的意思百匆?......"
B:"不對(duì)啊,wait是等待的意思加匈,await明明是用來等待異步執(zhí)行結(jié)果的,在這里怎么變成異步開始的標(biāo)志了雕拼?......"
A:"你說對(duì)了纵东,await是用來等待異步執(zhí)行結(jié)果的。但是await在使用時(shí)啥寇,后面需要跟一個(gè)Promise對(duì)象偎球,如果不是,會(huì)被轉(zhuǎn)為Promise對(duì)象辑甜,如上面的await 'async go!'相當(dāng)于如下代碼:

await new Promise((resolve, reject) => {  
      resolve('async go!');  
    })  

A:”所以衰絮,await并不是異步開始的標(biāo)志,而是因await對(duì)異步執(zhí)行的等待磷醋,導(dǎo)致await之后語句延后執(zhí)行猫牡。我們?cè)賹懚未a看看......“

引入Promise

function a(arg){  
  return new Promise((resolve, reject) => {  
      resolve(arg);  
    })  
}  
function b(arg){  
  return new Promise((resolve, reject) => {  
      resolve('你好,' + arg);  
    })  
}  

async function asynFunction(){  
  var aResult = await a('北京');  
  var bResult = await b(aResult);  

  console.log(bResult);  
}  

console.log('1');  
asynFunction();  
console.log('2');  

執(zhí)行結(jié)果:

1  
2  
你好邓线,北京  

A:”當(dāng)然淌友,我們往往需要通過async函數(shù)返回需要的數(shù)據(jù)......“

function a(arg){  
  return new Promise((resolve, reject) => {  
      resolve(arg);  
    })  
}  
function b(arg){  
  return new Promise((resolve, reject) => {  
      resolve('你好,' + arg);  
    })  
}  

async function asynFunction(){  
  var aResult = await a('北京');  
  var bResult = await b(aResult);  

  // 返回執(zhí)行結(jié)果  
  return bResult;  
}  

console.log('1');  
// 需要在then()方法中獲取執(zhí)行結(jié)果骇陈,原因是async函數(shù)的返回值同樣會(huì)被包裝成Promise對(duì)象  
asynFunction().then((v)=>{console.log(v)});  
console.log('2');  

執(zhí)行結(jié)果:

1  
2  
你好震庭,北京  

async函數(shù)其實(shí)也是一個(gè)包裝器,async和await配合你雌,包裝的是Promise器联,與Promise相比易讀性更好,更加符合代碼語義。
要點(diǎn)是:async函數(shù)是用來包裝Promise的

總結(jié)

Promise是用來包裝異步操作的主籍,所以僅僅包含同步代碼它是異步不了滴。
Promise把異步操作包裝起來逛球,是為了讓你的異步代碼看起來更直觀更優(yōu)雅千元。

async函數(shù)是用來包裝Promise的,所以僅僅包含同步代碼它也是異步不了滴颤绕。
async函數(shù)把Promise包裝起來幸海,是為了讓你的異步代碼看起來比Promise還要直觀還要
優(yōu)雅,能夠做到望文生義......

本文的初衷其實(shí)是希望大家不要望文生義......>_<

題外話

  • 為什么示例中的異步操作都在主線代碼之后執(zhí)行奥务?
    因?yàn)閑vent-loop,不了解點(diǎn)這里(密碼:yc3r)
  • 為什么Promise示例中總是有一個(gè)reject
    當(dāng)發(fā)生錯(cuò)誤物独、異常,未獲取到數(shù)據(jù)等情況時(shí)會(huì)用到它氯葬,不了解點(diǎn)這里
  • 為什么async函數(shù)中的await可以等待
    因?yàn)樗鼈兪莋enerator的語法糖挡篓,不了解點(diǎn)這里
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市帚称,隨后出現(xiàn)的幾起案子官研,更是在濱河造成了極大的恐慌,老刑警劉巖闯睹,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戏羽,死亡現(xiàn)場離奇詭異,居然都是意外死亡楼吃,警方通過查閱死者的電腦和手機(jī)始花,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門酷宵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忧吟,“玉大人斩披,你說我怎么就攤上這事垦沉。” “怎么了寡壮?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵况既,是天一觀的道長。 經(jīng)常有香客問我悲靴,道長癞尚,這世上最難降的妖魔是什么乱陡? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任憨颠,我火速辦了婚禮,結(jié)果婚禮上膜廊,老公的妹妹穿的比我還像新娘爪瓜。我一直安慰自己匙瘪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布薄货。 她就那樣靜靜地躺著谅猾,像睡著了一般鳍悠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敬矩,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天弧岳,我揣著相機(jī)與錄音凳忙,去河邊找鬼涧卵。 笑死艺演,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晓殊,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巫俺,長吁一口氣:“原來是場噩夢啊……” “哼介汹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嘹承,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤叹卷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后帝牡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒙揣,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懒震,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年个扰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锨匆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冬筒。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舞痰,死狀恐怖诀姚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赫段,我是刑警寧澤糯笙,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布给涕,位于F島的核電站,受9級(jí)特大地震影響恭应,放射性物質(zhì)發(fā)生泄漏耘眨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一褒纲、第九天 我趴在偏房一處隱蔽的房頂上張望莺掠。 院中可真熱鬧,春花似錦彻秆、人聲如沸结闸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽结耀。三九已至匙铡,卻和暖如春鳖眼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钦讳。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工愿卒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼开,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓衬衬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玉控。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狮惜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容