摘要:異步編程一般用來調(diào)取接口拉數(shù)據(jù)。通過我描述的篇幅,就知道異步編程比同步編程麻煩許多。遠古時期,異步編程是通過回調(diào)函數(shù)來解決的。
半理解系列--Promise的進化史
學(xué)過js的都知道,程序有同步編程和異步編程之分,同步就好比流水線,一步一個腳印,做完上個任務(wù)才做下一個,異步編程好比客服,客服接了一個電話,收到了一個任務(wù),然后把任務(wù)交給另外的人來處理,同時,繼續(xù)接聽下一個電話,等到另外的人處理完任務(wù)了,再通知客服,客服再反饋給第一個打電話的人。異步編程一般用來調(diào)取接口拉數(shù)據(jù)。
通過我描述的篇幅,就知道異步編程比同步編程麻煩許多。遠古時期,異步編程是通過回調(diào)函數(shù)來解決的。但是回調(diào)函數(shù)會有回調(diào)地獄的問題,回調(diào)的多了,維護人員看起來頭都大了,好比:taskC需要等待taskB做完(taskC才執(zhí)行),taskB又需要等待taskA做完(taskB才執(zhí)行)
function taskA (cb) { //..do task A cb() } function taskB(cb){ //..do task B cb() } function taskC(cb){ //..do task C cb() } taskA(function(){ taskB(function(){ taskC() }) }) ...以此類推,不斷循環(huán)嵌套,最終陷入地獄
而Promise就把這一系列的回調(diào),通過鏈?zhǔn)秸{(diào)用的方式連接起來,看起來清爽多了。同樣是上面的代碼,Promise可以這么寫(偽代碼)
new Promise().then(taskA).then(taskB).then(taskC)promise的使用
const promise = new Promise((resolve,reject)=>{ if (/*do something done*/){ resolve() // 可在此傳參數(shù) } else { // do something fail reject() // 可在此傳參數(shù) } }) promise.then(()=>{ //do something }).catch(e => { throw e})
上面的resolve,可以當(dāng)作task函數(shù)的cb回調(diào)函數(shù),當(dāng)resolve()執(zhí)行的時候,then方法中的回調(diào)會被執(zhí)行,如果是reject執(zhí)行,錯誤會被catch捕捉。
Promise的靜態(tài)方法
上面說的then和catch都是Promise的原型方法,即Promise.prototype.then/catch
Promise本身有兩個靜態(tài)方法,其作用類似 new Promise()
Promise.resolve()
const promise1 = Promise.resolve() 等價于 const promise2 = new Promise((reslove)=>{ reslove() })
使用該方法調(diào)用then方法
Promise.reject()
const promise1 = Promise.reject() 等價于 const promise2 = new Promise((resolve,reject)=>{ reject() })
使用該方法會被catch捕捉
Promise的鏈?zhǔn)秸{(diào)用
Promise的實例對象的then方法是可以重復(fù)調(diào)用的,then方法返回的是一個promise實例對象,所以可以重復(fù)調(diào)用then方法,并且(敲黑板),上一個then方法的返回值,會作為下一個then方法的參數(shù)傳遞
舉個栗子:
const promise = Promise.resolve("start") promise.then((params)=>{ console.log(params) // start return "aa" }).then((params) => { console.log(params) // aa return "bb" }).then((params)=>{ console.log(params) // bb return "cc" }) // 最后會返回一個狀態(tài)是resolve(cc)的promise對象:Promise?{: "cc"}
深入一下(又不會懷孕)
function badAsyncCall() { var promise = Promise.resolve(); promise.then(function() { // 任意處理 return "newVar"; }); return promise; } // 修改一下 function goodAsyncCall() { var promise = Promise.resolve(); return promise.then(function() { // 任意處理 return "newWar"; }); }
以上兩個寫法是不是很相似,唯一不同的就是return的處理。但調(diào)用,badAsynccall會出錯,而anAsyncCall能正確執(zhí)行,比如:
badAsyncCall().then(params => { console.log("bad--",params)}) // bad-- undefined goodAsyncCall().then(params => { console.log("good--",params)}) // good-- newWar
分析:第一種,錯誤寫法,首先在 promise.then 中產(chǎn)生的異常不會被外部捕獲,此外,也不能得到 then 的返回值,即使其有返回值。
原因:由于每次 promise.then 調(diào)用都會返回一個新創(chuàng)建的promise對象,第一種返回的promise,相當(dāng)于沒有調(diào)用過函數(shù)內(nèi)部的then方法,是一個全新的promise實例對象
結(jié)論: 統(tǒng)一使用promise鏈?zhǔn)秸{(diào)用,如:promise.then(taskA).then(taskB)
### async&await和promise的前世緣緣
promise說白了還是用回調(diào)的方式來解決異步問題,跟真正同步還是有差距的。
異步編程的最高境界,就是根本不用關(guān)心它是不是異步!(來之ruanyifeng老師的話)
所以,async&await方案出現(xiàn)了
用法:
function readFile(fileName) { return new Promise((resolve,reject)=>{ fs.readFile(fileName, function(error, data) { if (error) return reject(error); resolve(data); // 向thenc傳送異步讀取文件的數(shù)據(jù) }); }) } // 調(diào)用 readFile(fileName).then(function(data){ console.log("prmoise read files data --", data) }) // 等價于 async function asyncFn(fileName){ const data = await readFile(fileName) console.log("await data --", data) return data } asyncFn(fileName)
寫法是不是簡潔了許多!
其實async就是一個Promise的語法糖,它的返回值是一個promise對象,因此可以用then方法做鏈?zhǔn)秸{(diào)用(但參數(shù)就是async函數(shù)中的返回值,如上文的data?。。?/p>
async函數(shù)中還可以不使用promise,比如:
async function asyncFn(){ const data = await setTimeout(function(){ console.log("setTimeout") return "data" },1000) console.log("data",data) // Timeout {} 對象 } console.log("async",asyncFn()) // Promise {}
但這兩者,其實經(jīng)常混用,常見的就是readFile函數(shù)的做法啦
看懂以上的,才大家出一道題看看能不能懂;
async function asynFn(){ await Promise.resolve("aaa") const data = { b:"bb", c:function(){ return this.b } } return data //return 作為參數(shù)傳遞給then then的chain鏈也是通過return參數(shù)來不斷傳遞給后面的then } var cball = asynFn() cball.then(function(data){ console.log("data:",data) })
還有一種異步編程的語法糖: * & yield
跟async基本一樣,不在本文討論的重點。有興趣自行g(shù)oogle啦
參考資料:
async 函數(shù)的含義和用法
Promise 對象
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107430.html
摘要:簽訂協(xié)議的兩方分別是異步接口和。在異步函數(shù)中,使用異常捕獲的方案,代替了的異常捕獲的方案。需要注意的是,在異步函數(shù)中使異步函數(shù)用時要使用,不然異步函會被同步執(zhí)行。 同步與異步 通常,代碼是由上往下依次執(zhí)行的。如果有多個任務(wù),就必需排隊,前一個任務(wù)完成,后一個任務(wù)才會執(zhí)行。這種執(zhí)行模式稱之為: 同步(synchronous) 。新手容易把計算機用語中的同步,和日常用語中的同步弄混淆。如,...
摘要:系列種優(yōu)化頁面加載速度的方法隨筆分類中個最重要的技術(shù)點常用整理網(wǎng)頁性能管理詳解離線緩存簡介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實現(xiàn)的大排序算法一怪對象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁面加載速度的方法 隨筆分類 - HTML5 HTML5中40個最重要的技術(shù)點 常用meta整理 網(wǎng)頁性能管理詳解 HTML5 ...
摘要:系列種優(yōu)化頁面加載速度的方法隨筆分類中個最重要的技術(shù)點常用整理網(wǎng)頁性能管理詳解離線緩存簡介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實現(xiàn)的大排序算法一怪對象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁面加載速度的方法 隨筆分類 - HTML5 HTML5中40個最重要的技術(shù)點 常用meta整理 網(wǎng)頁性能管理詳解 HTML5 ...
摘要:截至目前,人類大腦是已知宇宙中最復(fù)雜的物體。但是天河二號也是一個龐大的家伙,它占地平方米,使用兆瓦的電力大腦只需瓦,耗資億美元建造。建議,通過查看可以以,美元購買多少來考慮計算機的狀態(tài)。 showImg(http://upload-images.jianshu.io/upload_images/13825820-c158f685feaf8ae6.jpg?imageMogr2/auto-...
閱讀 1432·2021-11-15 11:38
閱讀 3582·2021-11-09 09:47
閱讀 1984·2021-09-27 13:36
閱讀 3230·2021-09-22 15:17
閱讀 2565·2021-09-13 10:27
閱讀 2878·2019-08-30 15:44
閱讀 1193·2019-08-27 10:53
閱讀 2721·2019-08-26 14:00