Promise

在了解Promise之前需要了解js程序執(zhí)行機(jī)制.

我們都知道 JS 是一個(gè)單線(xiàn)程的語(yǔ)言刀脏,永遠(yuǎn)只有一個(gè)通道在運(yùn)行程序馆铁。通常來(lái)說(shuō)就是按書(shū)寫(xiě)順序執(zhí)行,先執(zhí)行程序A,再執(zhí)行程序B,這樣就會(huì)引出一個(gè)問(wèn)題
假如我有個(gè)圖片資源請(qǐng)求,請(qǐng)求時(shí)間很長(zhǎng),那么就會(huì)造成下面的代碼就要等這個(gè)圖片資源請(qǐng)求完成之后再執(zhí)行下一步程序,在這個(gè)過(guò)程中其他的程序不會(huì)被執(zhí)行,這樣是很不友好的.
還好程序員發(fā)明了異步和同步這兩種方式來(lái)處理問(wèn)題

異步執(zhí)行的好處

程序異步運(yùn)行,可以提高程序運(yùn)行的效率外厂,不必等一個(gè)程序跑完,再跑下一個(gè)程序誓焦,特別當(dāng)這兩個(gè)程序是無(wú)關(guān)的時(shí)候瓜贾。

模擬 JS 中異步的方法 —— setTimeout

function fn(){
  console.log('1');
  console.log('2');
}

function fn2() {
    setTimeout(()=>{
      console.log('3');
    },1000)
    console.log('4');
}
fn()
fn2()
//1
//2
//4
//3

這個(gè)例子中我們可以看到,我們定義了兩個(gè)函數(shù),fn()和fn2(),這里需要注意的是,fn()和fn2的書(shū)寫(xiě)順序,不管函數(shù)聲明順序是怎樣,只管函數(shù)的調(diào)用順序.上面的代碼是先調(diào)用fn()執(zhí)行1,2
再調(diào)用fn2(),這里先打印出4,再打印出3,這是因?yàn)閟etTimeout設(shè)置了1秒之后執(zhí)行

除了setTimeout可以模擬異步操作之外,回調(diào)函數(shù)也可以模擬異步,

function printAsync(str, callback) {
    console.log(str);
    if (callback) setTimeout(callback, 1000);
}
printAsync('aaa', function () {
    printAsync('bbb', function () {
        printAsync('ccc', function () {
            printAsync('ddd');
        })
    })
});
//aaa
//bbb
//ccc
//ddd

看到這么多的})是不是有點(diǎn)煩躁诺祸?這還是相對(duì)簡(jiǎn)單的,沒(méi)什么復(fù)雜的業(yè)務(wù)邏輯,像這種多個(gè)回調(diào)函數(shù)的多層嵌套會(huì)讓代碼的可讀性直線(xiàn)下降,因此又稱(chēng)為回調(diào)地獄祭芦。

Promise

Promise是一種處理異步的方式,解決了函數(shù)的異步回調(diào)問(wèn)題,在通常情況下,如果使用多級(jí)回調(diào)函數(shù),代碼很難維護(hù),這樣就衍生了一種新的方式更好的處理這個(gè)問(wèn)題.Promisse還有個(gè)好處就是捕捉錯(cuò)誤信息.

Promise對(duì)象有以下兩個(gè)特點(diǎn)筷笨。

(1)對(duì)象的狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作龟劲,有三種狀態(tài):pending(進(jìn)行中)胃夏、fulfilled(已成功)和rejected(已失敗)昌跌。只有異步操作的結(jié)果仰禀,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無(wú)法改變這個(gè)狀態(tài)蚕愤。這也是Promise這個(gè)名字的由來(lái)答恶,它的英語(yǔ)意思就是“承諾”,表示其他手段無(wú)法改變审胸。

(2)一旦狀態(tài)改變亥宿,就不會(huì)再變卸勺,任何時(shí)候都可以得到這個(gè)結(jié)果砂沛。Promise對(duì)象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected曙求。只要這兩種情況發(fā)生碍庵,狀態(tài)就凝固了,不會(huì)再變了悟狱,會(huì)一直保持這個(gè)結(jié)果静浴,這時(shí)就稱(chēng)為 resolved(已定型)。如果改變已經(jīng)發(fā)生了挤渐,你再對(duì)Promise對(duì)象添加回調(diào)函數(shù)苹享,也會(huì)立即得到這個(gè)結(jié)果。這與事件(Event)完全不同浴麻,事件的特點(diǎn)是得问,如果你錯(cuò)過(guò)了它,再去監(jiān)聽(tīng)软免,是得不到結(jié)果的宫纬。

我們通過(guò) 一個(gè)例子來(lái)看看Promise的具體用法

let ajax = function() {
  console.log('執(zhí)行');
  return new Promise((resolve, reject) => {
    setTimeout(()=>{
      resolve()
    },1000)
  })
}

ajax().then(()=>{
  console.log('promise'+':'+'timeout1');
})
//執(zhí)行
//promise timeout1

then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞esolved時(shí)調(diào)用膏萧,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞ejected時(shí)調(diào)用漓骚。其中蝌衔,第二個(gè)函數(shù)是可選的,不一定要提供蝌蹂。這兩個(gè)函數(shù)都接受Promise對(duì)象傳出的值作為參數(shù)噩斟。

Promise還可以通過(guò)catch來(lái)捕獲錯(cuò)誤,我們來(lái)看下代碼的實(shí)現(xiàn)

let ajax = function(num){
  console.log('開(kāi)始執(zhí)行');
  return new Promise(function(resolve,reject){
    if(num > 5){
      resolve()
    }else{
      throw new Error('出錯(cuò)了')
    }
  })
}

ajax(1).then(()=>{
  console.log('log',6);
}).catch((err)=>{
  console.log('catch',err);
})
ajax(6).then(()=>{
  console.log('log',6);
}).catch((err)=>{
  console.log('catch',err);
})


image.png
image.png

如果出現(xiàn)錯(cuò)誤,可以得知哪一步出錯(cuò),可以幫助我們解決bug

除了這些還有一些高級(jí)用法,

function loadImg(src){
  return new Promise((resolve,reject)=>{
    let img = document.createElement('img')
    img.src = src
    img.onload = function(){
      resolve(img)
    }
    img.onerror = function(err){
      reject(err)
    }
  })
}

function showImgs(imgs){
  imgs.forEach(function(img){
    document.body.appendChild(img)
  })
}

Promise.all([
  loadImg('https://cdn.pixabay.com/photo/2018/06/10/00/11/seagull-3465550__340.jpg'),
  loadImg('https://cdn.pixabay.com/photo/2018/06/10/21/29/white-currant-3467373__340.jpg'),
  loadImg('https://cdn.pixabay.com/photo/2018/06/12/03/41/butterbur-3469942__340.jpg'),
]).then(showImgs)

通過(guò)Promise.all(),可以等到三張圖片數(shù)據(jù)全部加載完成之后再渲染到頁(yè)面上

當(dāng)然還有一種高級(jí)用法

function loadImg(src){
  return new Promise((resolve,reject)=>{
    let img = document.createElement('img')
    img.src = src
    img.onload = function(){
      resolve(img)
    }
    img.onerror = function(err){
      reject(err)
    }
  })
}

function showImgs(img){
  
    document.body.appendChild(img)

}

Promise.race([
  loadImg('https://cdn.pixabay.com/photo/2018/06/10/00/11/seagull-3465550__340.jpg'),
  loadImg('https://cdn.pixabay.com/photo/2018/06/10/21/29/white-currant-3467373__340.jpg'),
  loadImg('https://cdn.pixabay.com/photo/2018/06/12/03/41/butterbur-3469942__340.jpg'),
]).then(showImgs)

Promise.race的用法就是孤个,只要Promise狀態(tài)改變亩冬,有數(shù)據(jù)到來(lái),我就把第一條到來(lái)的數(shù)據(jù)渲染到頁(yè)面上硼身,其他的不再響應(yīng)硅急。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市佳遂,隨后出現(xiàn)的幾起案子营袜,更是在濱河造成了極大的恐慌,老刑警劉巖丑罪,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荚板,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吩屹,警方通過(guò)查閱死者的電腦和手機(jī)跪另,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)煤搜,“玉大人免绿,你說(shuō)我怎么就攤上這事〔炼埽” “怎么了嘲驾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)迹卢。 經(jīng)常有香客問(wèn)我辽故,道長(zhǎng),這世上最難降的妖魔是什么腐碱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任誊垢,我火速辦了婚禮,結(jié)果婚禮上症见,老公的妹妹穿的比我還像新娘喂走。我一直安慰自己,他們只是感情好筒饰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布缴啡。 她就那樣靜靜地躺著,像睡著了一般瓷们。 火紅的嫁衣襯著肌膚如雪业栅。 梳的紋絲不亂的頭發(fā)上秒咐,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音碘裕,去河邊找鬼携取。 笑死,一個(gè)胖子當(dāng)著我的面吹牛帮孔,可吹牛的內(nèi)容都是我干的雷滋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼文兢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼晤斩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起姆坚,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤澳泵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后兼呵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體兔辅,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年击喂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了维苔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡懂昂,死狀恐怖介时,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忍法,我是刑警寧澤潮尝,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站饿序,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏羹蚣。R本人自食惡果不足惜原探,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顽素。 院中可真熱鬧咽弦,春花似錦、人聲如沸胁出。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)全蝶。三九已至闹蒜,卻和暖如春寺枉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绷落。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工姥闪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砌烁。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓筐喳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親函喉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子避归,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355