摘要:回調地獄的問題在于寫法過于繁瑣不夠優雅代碼維護炒雞蛋疼,所以一直被前端程序猿所詬病,尤其是維護類似代碼的時候簡直日了一群哈士奇。,對象狀態以和為分水嶺。方法返回一個帶有拒絕原因參數的對象摘自對的解釋。并且返回的也是一個對象。
這是一段旁白
“異步虐我千百遍,我待異步如初戀”!!
做前端的同學做異步肯定都不陌生。因為JavaScript是單線程語言(也就是說不支持多線程編程,這不是廢話么啊喂!),所以在JavaScript中處理異步問題也是經過了幾代人的踩坑和開荒才有了今天的“花里胡哨”的解決方案。
利用回調來實現異步是一直以來非常有效的解決方案,而且經久不衰。其背后的原理很簡單,就是利用JavaScript中可以將函數作為參數傳入另一個函數(萬物皆對象)。舉個栗子:
function callBack() { console.log("回調啦回調啦!!!"); } function main(cb) { console.log("我會運行很久!") cb(); } main(callBack);
下面一段代碼中實現兩個函數 callBack 和 main。隨后將 callBack 傳入到 main 函數中,當 main 函數執行到一個階段時候會調用傳入的回調函數 ( 此處是當main函數運行到底部時候就調用了回調函數 )。運行結果不言而喻:
這樣的寫法看起來貌似還行,寫法簡單明了,一看就懂。但是這里筆者要吐槽下去年自己的智商,且聽慢慢道來:
去年在重構項目的時候,有一個頁面需要展示 4 個下拉框而且下拉框的數據需要從后臺拉取。所以筆者在ComponentWillMount(React項目)方法中執行了拉取數據的動作而且是分開獨立拉取,類似于:
...... ComponentWillMount() { let data = {}; fetchSelect1(); fetchSelect2(); fetchSelect3(); fetchSelect4(); } ......
最后在四個方法中將數據存儲到 data 對象中以供渲染選擇框,但是后面出現了一個意想不到問題:總會有一個下拉框數據拉取失敗。所以不得已采用了回調方式來處理,這里再狠狠得吐槽一下自己,如果那時候會用Promise,也不會那么尷尬。下面貼一下當時的代碼:
/* fetch data source prop selects */ router.get("/fetch-selects", function(req, resp, next) { let path1 = config.BACKEND_API.BASE_URL + "/datasource/frequency"; var reponseData = {}; httpAgent.httpRequest({}, "JSON", config.BACKEND_API.TYPE, config.BACKEND_API.HOST, config.BACKEND_API.PORT, path1, "GET", function(data) { reponseData.frequency = data; let path2 = config.BACKEND_API.BASE_URL + "/datasource/category"; httpAgent.httpRequest({}, "JSON", config.BACKEND_API.TYPE, config.BACKEND_API.HOST, config.BACKEND_API.PORT, path2, "GET", function(data) { reponseData.category = data; let path3 = config.BACKEND_API.BASE_URL + "/datasource/type"; httpAgent.httpRequest({}, "JSON", config.BACKEND_API.TYPE, config.BACKEND_API.HOST, config.BACKEND_API.PORT, path3, "GET", function(data) { reponseData.type = data; let path4 = config.BACKEND_API.BASE_URL + "/datasource/process/type"; httpAgent.httpRequest({}, "JSON", config.BACKEND_API.TYPE, config.BACKEND_API.HOST, config.BACKEND_API.PORT, path4, "GET", function(data) { reponseData.process = data; resp.json(reponseData); }, function(code, body) { }) }, function(code, body) { }) }, function(code, body) { }) }, function(code, body) { }) });
當時用的Node項目做的中間層,這是一個路由。可以看出來其實就是在拉取完第一條數據后再調用另一個函數來拉取第二條數據,如此嵌套下去。好在只需要拉取 4 條數據,那如果有10條乃至100條數據需要拉取怎么辦?那豈不是需要嵌套出一個很深很深的代碼結構么?這就是臭名昭著的“回調地獄”。“回調地獄”的問題在于寫法過于繁瑣不夠優雅、代碼維護炒雞蛋疼,所以一直被前端程序猿所詬病,尤其是維護類似代碼的時候簡直日了一群哈士奇。不僅僅是想死的心了,完全想刪庫走人啊喂!
Promise當前端異步工作處于水深火熱中時,一個英雄踏著七彩祥云而來,他,就是 Promise。讓我們相信:一個承諾,終究會被兌現。
Promise的由來Promise 先由社區提出來的概念,主要是用于解決前端的異步問題,慶幸的是它在ES6中也得到了實現。什么是Promise
Promise 是一個狀態機。這么說可能有點不好懂,上個代碼先:
new Promise(function(resolve, reject) { try { resolve("Success") } catch (e) { reject(e); } })
從上面可以看出幾個重要的點:
1,Promise是一個構造函數。
2,新建Promise對象需要傳入執行器函數 (executor function)。
3,執行器函數中有兩個參數 resolve 和 reject。這兩個也是執行器函數。
對此來解釋下什么叫狀態機
Promise對象有三個狀態:pending, fulfilled, rejected,沒圖說個JB?
從圖中可以看出,Promise對象的初始狀態是pending ,如果經過了 resolve 方法,狀態置為 fulfilled ;如果經過了 reject 方法,狀態置為 rejected 。而且有三點需要明確:
1,Promise對象的狀態轉換只有 pending--->fulfilled 或者 pending--->rejected。沒有其它形式的轉換。
2,Promise 對象的狀態一經轉換則永久凍結,意思就是說比如狀態被置為 fulfilled 后,無法再回到 pending。
3,Promise對象狀態以resolve 和 reject為分水嶺。調用這個兩個方法之前,都處于pending狀態。
Promise.resolve(value)方法返回一個以給定值 value 解析后的 Promise 對象
摘自MDN對 Promise.resolve() 的解釋。簡單的理解就是它用來返回任務執行成功后的返回值。Promise對象調用完這個方法后狀態就被置為 fulfilled。
Promise.reject()Promise.reject(reason)方法返回一個帶有拒絕原因reason參數的 Promise 對象
摘自MDN對 Promise.reject() 的解釋。Promise對象調用完這個方法后狀態就被置為 rejected。
Promise.prototype.then()看到這里可能會有這么一個問題:既然Promise用 resolve 和reject 返回處理結果,那如何獲取到這個結果呢?那么then()就大有可為了。從小標題可以看出 then 方法被放在Promise的原型上,也就是說任何一個Promise對象都可以調用這個方法,不管何時何地。then()方法的參數為兩個個執行器函數,第一個函數用來處理 resolve() 返回值,第二個函數用來處理 reject() 返回值。并且then()返回的也是一個 Promise 對象。舉個
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96783.html
摘要:用原生寫一個多動癥的簡歷預覽地址源碼地址最近在知乎上看到方應杭用寫了一個會動的簡歷,覺得挺好玩的,研究一下其實現思路,決定試試用原生來實現。 用原生js寫一個多動癥的簡歷 預覽地址源碼地址 最近在知乎上看到@方應杭用vue寫了一個會動的簡歷,覺得挺好玩的,研究一下其實現思路,決定試試用原生js來實現。 showImg(https://segmentfault.com/img/remot...
JavaScript異步與回調 一、前言 首先我們要記住的是異步和并行有著本質的區別。 并行,簡單來說是一般指并行計算,就是說同一時刻有多條指令同時被執行,這些指令可能執行于同一CPU的多核上,或者多個CPU上,或者多個物理主機甚至多個網絡中。 同步,一般指按照預定的順序依次執行任務,只有當上一個任務完成后,才開始執行下一個任務。 異步,與同步相對應,異步指的是讓CPU暫時擱置當前任...
摘要:使用官方的的另外一種版本和一起使用自動配置了一個項目支持。需要的依賴都在文件中。帶靜態類型檢驗,現在的第三方包基本上源碼都是,方便查看調試。大型項目首選和結合,代碼調試維護起來極其方便。 showImg(https://segmentfault.com/img/bVbrTKz?w=1400&h=930); 阿特伍德定律,指的是any application that can be wr...
閱讀 1712·2023-04-26 02:30
閱讀 1040·2021-11-10 11:36
閱讀 1386·2021-10-08 10:14
閱讀 3514·2021-09-28 09:35
閱讀 1556·2021-08-23 09:47
閱讀 2549·2019-08-30 15:56
閱讀 1475·2019-08-30 15:44
閱讀 1769·2019-08-30 13:59