使用Promise模式來簡化JavaScript的異步回調

2020-12-13 站長之家

使用Promise模式來簡化JavaScript的異步回調

網頁的交互越來越複雜,JavaScript 的異步操作也隨之越來越多。如常見的 ajax 請求,需要在請求完成時響應操作,請求通常是異步的,請求的過程中用戶還能進行其他的操作,不會對頁面進行阻塞,這種異步的交互效果對用戶來說是挺有友好的。但是對於開發者來說,要大量處理這種操作,就很不友好了。異步請求完成的操作必須預先定義在回調函數中,等到請求完成就必須調用這個函數。這種非線性的異步編程方式會讓開發者很不適應,同時也帶來了諸多的不便,增加了代碼的耦合度和複雜性,代碼的組織上也會很不優雅,大大降低了代碼的可維護性。情況再複雜點,如果一個操作要等到多個異步 ajax 請求的完成才能進行,就會出現回調函數嵌套的情況,如果需要嵌套好幾層,那你就只能自求多福了。

先看看下面這個常見的異步函數。

var showMsg = function(){

setTimeout(function(){

alert( 『hello』 );

}, 5000 );

};

如果要給該函數添加回調,通常會這麼幹。

var showMsg = function( callback ){

setTimeout(function(){

alert( 『hello』 );

// 此處添加回調

callback();

}, 5000 );

};

如果是使用 easy.js 的 Promise,添加回調的方法就會優雅多了,前提是需要將原函數封裝成一個 promise 實例。

var showMsg = function(){

// 構造promise實例

var promise = new E.Promise();

setTimeout(function(){

alert( 『hello』 );

// 改變promise的狀態

promise.resolve( 『done』 );

}, 5000 );

// 返回promise實例

return promise;

};

將一個普通的函數封裝成一個 promise 實例,有3個關鍵步驟,第一步是在函數內部構造一個 promise 實例,第二步是部署函數執行完去改變 promise 的狀態為已完成,第三步就是返回這個 promise 實例。每個 promise 實例都有3種狀態,分別為 pending(未完成)、resolved(已完成,成功)、rejected(已拒絕,失敗)。下面再來看看如何添加回調。

showMsg().then(function( str ){

// 回調添加到這裡來了

callback( str );

});

這樣就將回調函數和原來的異步函數徹底的分離了,從代碼組織上看,優雅了很多。resolve 接受一個參數,該參數就可以輕鬆實現將數據傳送給使用 then 方法添加的回調中。

對於 ajax 請求,easy.js 直接將 ajax 方法封裝成了 promise 對象,可以直接添加 then 方法來回調。

E.ajax({

url : 『test1.php』,

type : 『GET』

})

then(function(){

// 添加請求成功的回調

}, function(){

// 添加請求失敗的回調

});

then 方法接受2個函數作為參數,第一個函數是已完成的回調,第二個就是已失敗的回調。

如果有上面提到的多個 ajax 請求的情況呢?那麼就要用到 when 這個方法了。該方法可以接受多個 promise 實例作為參數。

var requests = E.when(E.ajax({

url : 『test1.php』,

type : 『GET』

}), E.ajax({

url : 『test2.php』,

type : 『GET』

}));

requests.then(function( arg1, arg2 ){

console.log( 『success:』 + arg1[0] + arg2[0] );

}, function( arg1, arg2 ){

console.log( 『failure:』 + arg1 + arg2 );

});

when 方法是將多個 promise 實例存到一個數組中,等到該數組的所有 promise 實例都是已完成狀態才去執行已完成的回調,一旦有一個實例是已拒絕的狀態,則立即執行已拒絕的回調。

Promise 模式是 CommonJS 的規範之一。很多主流的 JavaScript 庫都有相應的實現,如 jQuery 和 Dojo 中,都有 Deferred 去實現這些功能。在這裡還是要吐槽下 jQuery 的 Deferred,撇開其內部使用,這應該用戶使用率最低的一個模塊了,這和其較複雜的使用方式有一定的關係。

如果你想深入的研究 easy.js 的 promise 源碼,可以查看點擊這兒的連結。

文章來源:夜雨帶刀博客

相關焦點

  • JavaScript異步編程助手:Promise模式
    通過這些庫,開發人員能夠在實際編程中使用Promise模式,每個Promise都擁有一個叫做then的唯一接口,當Promise失敗或成功時,它就會進行回調。它代表了一種可能會長時間運行而且不一定必須完成的操作結果。這種模式不會阻塞和等待長時間的操作完成,而是返回一個代表了承諾的(promised)結果的對象。
  • JavaScript 異步與 Promise 實現
    在閱讀本文之前,你應該已經了解JavaScript異步實現的幾種方式:回調函數,發布訂閱模式,Promise,生成器(Generator),其實還有
  • JavaScript異步與Promise實現
    發布訂閱模式,Promise,生成器(Generator),其實還有async/await方式,這個後續有機會會介紹。異步,表示在將來某一時刻執行,那麼Promise也必須可以表示一個將來值;異步任務,可能成功也可能失敗,則Promise需要能完成事件,標記其狀態值(這個過程即決議-resolve,下文將詳細介紹);可能存在多重異步任務,即異步任務回調中有異步任務,所以Promise還需要支持可重複使用,添加異步任務(表現為順序鏈式調用,註冊異步任務,這些異步任務將按註冊的順序執行
  • 從promise讀懂JavaScript異步編程
    從《setTimeout(fn,0)函數剖析JavaScript的執行機制》一文已經說明了同步和異步的區別,而這篇文章將更深入的去理解什麼是JS的異步編程,以及promise,async,await等的使用。從而更好的為前端編程打好堅實的基礎。
  • JS異步編程,回調函數與promise
    它由社區最早提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了ES6之前,JavaScript中異步編程分為3類:DOM事件(如onclick)、網絡請求(如ajax)、定時器(setTimeout/setInterval)。他們均使用回調函數來進行異步調用。當回調函數中嵌套了回調函數,甚至是多層回調時,編碼就不夠直觀了。而使用Promise就能通過同步的編碼方式實現異步調用。
  • 理解異步之美--- Promise與async await(一)
    如果表達有誤的地方,還望評論區指出~不多嗶嗶,坐穩扶好,發車了~你可能會放出一個怪物異步與同步相比,最難以掌控的就是異步的任務會什麼時候完成和完成之後的回調問題。在你不知道的javascript一書中,對於回調的信任問題做了闡述當你使用第三方的庫的方法處理回調時很有可能遇到以下信任內容:怎麼解決???? 這種信任問題該怎麼辦?
  • JavaScript之Promise對象
    javascript是單線程語言,所以都是同步執行的,要實現異步就得通過回調函數的方式,但是過多的回調會導致回調地獄,代碼既不美觀,也不易維護,所以就有了promise;Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。
  • 拆解 JavaScript 中的異步模式
    callback、promise、generator、async await 甚至 RxJS。我最初接觸不同的異步模式時,曾想當然的覺得 promise 就是比 callback 好, async await 比就是比 promise 優雅,會把它們割裂起來看待。後來發現也不完全這樣,各種異步模式之間其實存在著關聯,也有著各自擅長的場景。
  • 從JavaScript的事件循環到Promise
    於異步IO,比如ajax,寫代碼的時候都是順序執行的,但是在真正處理請求的時候,有一個單獨的瀏覽器線程來處理,並且在處理完成後會觸發回調。這種情況下,參與異步過程的其實有2個線程主體,一個是javascript的主線程,另一個是瀏覽器線程。
  • JavaScript Promise啟示錄
    近幾年隨著JavaScript開發模式的逐漸成熟,CommonJS規範順勢而生,其中就包括提出了Promise規範,Promise完全改變了js異步編程的寫法,讓異步編程變得十分的易於理解。; }); });});這也就是我們常說的回調金字塔,當異步的任務很多的時候,維護大量的callback將是一場災難。當今Node.js大熱,好像很多團隊都要用它來做點東西以沾沾「洋氣」,曾經跟一個運維的同學聊天,他們也是打算使用Node.js做一些事情,可是一想到js的層層回調就望而卻步。好,扯淡完畢,下面進入正題。
  • 有關JavaScript中回調函數的所有內容!
    回調函數是每個 JS 開發人員都應該知道的概念之一。回調用於數組,計時器函數,promise,事件處理程序等中。在本文中,會解釋回調函數的概念。另外,還會幫助智米們區分兩種回調:同步和異步。persons.map(greet)接受person數組的每一項,並使用每一項作為調用參數來調用函數greet():greet('小智'),greet('王大冶')。有趣的是persons.map(greet)方法接受greet()函數作為參數。
  • Promise 初使用
    本文介紹了Promise的基本使用,並給出了用它來改寫異步回調函數的套路。1 簡介本文介紹了Promise的構造器的使用語法,promise對象的三種狀態及狀態轉換,並分析了其經典格式的執行流程,最後給出了用它來改寫異步代碼的套路,並予以實踐。你最好需要有一些ajax,箭頭函數的基礎這會理解更深一些。當然啦,也有可能你還沒有需要用它們的時候。
  • 大前端進擊之路|JavaScript異步編程
    我們在燒水的過程中去幹了別的事情,就屬於異步模式,異步模式中不會等待異步任務的結束才開始執行下一個同步的任務,都是開啟過後就立即執行下一個任務。異步模式對於JS很重要,沒有異步模式的話我們就無法同時處理大量的耗時任務,就會給用戶帶來卡頓和假死的體驗。對於我們開發者來說,會給我們打開代碼執行的順序混亂的問題。
  • JavaScript中的Promise使用詳解
    ,一般就一到兩級,但是某些情況下,回調嵌套很多時,代碼就會非常繁瑣,會給我們的編程帶來很多的麻煩,這種情況俗稱——地獄回調。那麼如何解決地獄回調,保持我們的代碼簡短,這時Promise就出場了,Promise對象可以理解為一次執行的異步操作,使用Promise對象之後可以使用一種鏈式調用的方式來組織代碼;讓代碼更加的直觀。
  • 把Node.js 中的回調轉換為 Promise
    最後通過引入 async/await 關鍵字來提供更好的體驗並提高了可讀性。即使有了新的方法,但是仍然有許多使用回調的原生模塊和庫。在本文中,我們將討論如何將 JavaScript 回調轉換為 Promise。ES6 的知識將會派上用場,因為我們將會使用 展開操作符之類的功能來簡化要做的事情。
  • 大前端進擊之路(二):JavaScript異步編程
    我們在燒水的過程中去幹了別的事情,就屬於異步模式,異步模式中不會等待異步任務的結束才開始執行下一個同步的任務,都是開啟過後就立即執行下一個任務。異步模式對於JS很重要,沒有異步模式的話我們就無法同時處理大量的耗時任務,就會給用戶帶來卡頓和假死的體驗。對於我們開發者來說,會給我們打開代碼執行的順序混亂的問題。
  • 把 Node.js 中的回調轉換為 Promise
    最後通過引入  async/await  關鍵字來提供更好的體驗並提高了可讀性。即使有了新的方法,但是仍然有許多使用回調的原生模塊和庫。在本文中,我們將討論如何將 JavaScript 回調轉換為 Promise。ES6 的知識將會派上用場,因為我們將會使用 展開操作符之類的功能來簡化要做的事情。
  • [完結篇] - 理解異步之美 --- promise與async await(三)
    但是javascript並沒有這種結果(ps:ES6提供了set,而且也可以實現迭代器),但是我們對這種模式實用的並不是特別多。迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內部表示。
  • JS異步編程 | Promise 實現原理解析
    在傳統的異步編程中,如果異步之間存在依賴關係,我們就需要通過層層嵌套回調來滿足這種依賴。如果嵌套層數過多,可讀性和可維護性都變得很差,產生所謂「回調地獄」,而Promise將回調嵌套改為鏈式調用,增加可讀性和可維護性。下面我們就來一步步實現一個Promise。
  • 初學者應該看的JavaScript Promise 完整指南
    與回調相比,Promise 具有許多優點,例如:提供組合錯誤處理。* 更好的流程控制,可以讓異步並行或串行執行。回調更容易形成深度嵌套的結構(也稱為回調地獄)。當在 promise 實例中使用.then方法時,可以在Promise 「完成」 時得到通知。讓我們來看一個例子。Promise 僅僅只是回調?並不是。承諾不僅僅是回調,但它們確實對.then和.catch方法使用了異步回調。Promise 是回調之上的抽象,我們可以連結多個異步操作並更優雅地處理錯誤。來看看它的實際效果。