摘要:常見問題總結如何中斷的缺點之一就是無法讓中斷如上代碼如何讓的鏈式調用中斷一種方法是在中直接拋錯這樣就不會執行直接跳到方法打印但此方法并沒有實際中斷另一種方法就是在中一個新的但不改變其狀態這樣該就一直處于狀態即不會執行后面任何方法中斷有啥用
promise常見問題總結 promise如何中斷
promise的缺點之一就是無法讓promise中斷
Promise.resolve().then(() => { console.log("then 1") }).then(() => { console.log("then 2") }).then(() => { console.log("then 3") }).catch((err) => { console.log(err) })
如上代碼如何讓promise的鏈式調用中斷?
一種方法是在then 1中直接拋錯, 這樣就不會執行then 2, then 3, 直接跳到catch方法打印err(但此方法并沒有實際中斷)
Promise.resolve().then(() => { console.log("then 1") throw new Error("xxx") }).then(() => { console.log("then 2") }).then(() => { console.log("then 3") }).catch((err) => { console.log(err) })
另一種方法就是在then 1中return 一個新的Promise,但不改變其狀態,這樣該Promise就一直處于pedding狀態,即不會執行后面任何方法
Promise.resolve().then(() => { console.log("then 1") return new Promise(() => {}) }).then(() => { console.log("then 2") }).then(() => { console.log("then 3") }).catch((err) => { console.log(err) })
中斷有啥用? ---------- 可以讓我想到超時中斷問題
假設我們要用promsie自己封裝一個ajax, 設置超時中斷時間,如果沒返回就不用返回了, 返回也不做處理了,不重要(雖然和上面的原理沒關系,但不重要,上面是一個promsie的鏈式調用中斷,此例是實際應用中的問題,你管我用幾個promsie呢, 想到了記錄一下)
function wrap(p1) { let abort let p2 = new Promise((resolve, reject) => { abort = reject }) let p = Promise.race([p1, p2]) // 將延時promise的reject方法掛在到p1與p2的race后的promise上, 可以在方法外通過調用p的cancel方法,來觸發p2的reject p.cancel = abort return p } let fn = wrap(new Promise((resolve, reject) => { // 假設1秒后ajax返回, 調用resolve setTimeout(() => { resolve() }, 1000) })) fn.then(() => { console.log("ok") }).catch(() => { console.log("err") }) // 設置延時時間500ms, 如果500ms數據買回來,就中斷 setTimeout(() => { fn.cancel() }, 500)promise 微任務的執行順序
之前的promise中斷好歹還可以強說有點用,下面這種例子,誰要是沒事寫在生產代碼中,直接開除好吧~~~尋思尋思得了
const p = Promise.resolve(); ;(()=>{ const implicit_promise = new Promise(resolve =>{ const promise = new Promise(resolve=>{ resolve(p) }); promise.then(()=>{ console.log("after:await"); resolve() }) }); return implicit_promise })(); p.then(()=>{ console.log("tick:a"); }).then(()=>{ console.log("tick:b"); }).then(()=>{ console.log("tick:c"); });
首先第一行生成一個resolve成功態的promise,然后自執行函數同步代碼直接執行,
第5行resolve(p), 這里要知道resolve一個promsie要等到該promise執行then方法后才能拿到返回值
也就是說第7行的then要等到p的返回值拿到之后才執行
下面先把下面的鏈式編程拆一下
const p = Promise.resolve(); ;(()=>{ const implicit_promise = new Promise(resolve =>{ const promise = new Promise(resolve=>{ resolve(p) }); promise.then(()=>{ console.log("after:await"); resolve() }) }); return implicit_promise })(); let p1 = p.then(()=>{ console.log("tick:a"); }) p1.then(()=>{ console.log("tick:b"); }).then(()=>{ console.log("tick:c"); });
自執行函數執行完,執行p1的回調先打印tick:a,且由于沒有return值,所以默認return一個新的promise也就是p1接收的心promise
然后緊接著p1調用then方法,之后第7行也調用then方法, 所以相繼打印tick:b和after:await
等到tick:b執行完返回一個新的promise,這才執行tick:c
所以打印順序為 tick:a ==> tick:b ==> after:await ==> tick:c
這就是面向面試學習的精髓
async function async1(){ console.log("async1 start") await async2(); console.log("async1 end") } async function async2(){ console.log("async2") } console.log("script start") setTimeout(function(){ console.log("setTimeout") },0) async1(); new Promise(function(resolve){ console.log("promise1") resolve(); }).then(function(){ console.log("promise2") }) console.log("script end");
這段代碼在很多地方看到了,其他執行順序很容易理解,唯一的問題就在于async1 end什么時候執行,我們先不考慮這行console
就很容易可以得到以下結果
// script start (同步代碼,上面是兩個函數還沒有調用) // async1 start (調用async1的時候執行async1函數,打印async1 start) // async2 (在async1中調用async2, 打印async2) // promsie1 (同步代碼執行到new Promise, 在executor中執行同步代碼, 打印promise1) // script end (promise1 打印后暫不執行promsie2因為then回調是在微任務中,先執行同步代碼, 打印script end) // promise2 (同步代碼執行完, 清空微任務) // setTimeout (宏任務執行)
那么問題就在于async1 end什么時候執行
毫無疑問現在的問題在于await的原理,他肯定也是異步的微任務, 問題在于async1 end和promise2 誰先執行,
首先在node環境下測試是promise2先執行,但是在chrome中執行是async1 end先執行
由此可以得出await轉化promise
在node中
async2().then(() => { console.log("async1 end") }) // 你以為是這么轉化的?我也是這么以為的,**但是**在node中的then函數中它默認用Promise又包裹一層所以是這樣的 async2().then(() => { return Promise.resolve().then(() => { console.log("async1 end") }) }) // 有點惡心了~~~我測試的版本是v8.6.0以上版本 // 這樣的執行順序就是async1 end 在promise2之后 // script start // async1 start // async2 // promise1 // script end // promise2 // async1 end // setTimeout
但在chrome(74.0.3729.169)中的轉化應該是只有一個then,then中直接調用console,所以在瀏覽器中就是
// script start // async1 start // async2 // promise1 // script end // async1 end // promise2 // setTimeout
這個轉化過程是通過結果推出來的,總之開發環境還是要避免這樣的代碼出現
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/104934.html
摘要:引擎線程也稱為內核,負責處理腳本程序例如引擎引擎線程負責解析腳本,運行代碼。對象代表一個未完成但預計將來會完成的操作。注意一旦新建就會立即執行它屬于,無法取消。 寫在前面: 第一遍學Promise時, 只是大概過了一遍, 感覺學的不夠深入, 這一篇算是對之前的一個總結吧. Promise在ES6中也屬于一個較難理解的一部分; 所以在學習一個比較難理解的知識點時, 我們可以圍繞這個知識點...
摘要:眾所周知和都屬于上述異步任務的一種那到底為什么和會有順序之分這就是我想分析總結的問題所在了和的作用是為了讓瀏覽器能夠從內部獲取的內容并確保執行棧能夠順序進行。只要執行棧沒有其他在執行,在每個結束時,隊列就會在回調后處理。 前言 我是在做前端面試題中看到了setTimeout和Promise的比較,然后第一次看到了microtask和macrotask的概念,在閱讀了一些文章之后發現沒有...
摘要:那個率先改變的實例的返回值,就會傳遞給的回調函數。函數對函數的改進,體現在以下四點內置執行器。進一步說,函數完全可以看作多個異步操作,包裝成的一個對象,而命令就是內部命令的語法糖。中的本質就是沒有的隱藏的組件。 1、原型 - jquery使用showImg(https://segmentfault.com/img/bVbwNcY?w=692&h=442);注釋 : 實例雖然不同,但是構...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:以下總結了異步編程的種方式回調函數回調函數異步編程的最基本的方式。由小組的成員在規范中提出,目的是為異步編程提供統一接口。結尾參考文章異步編程參考文章使用詳解 前言 Javascript語言的執行環境是單線程。 單線程: 一次只能完成一個任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務。 單線程的好處是執行環境簡單,壞處是在一些耗時的任務上會堵塞進程。比如讀取一個...
閱讀 3679·2021-11-23 09:51
閱讀 1676·2021-10-22 09:53
閱讀 1357·2021-10-09 09:56
閱讀 863·2019-08-30 13:47
閱讀 2164·2019-08-30 12:55
閱讀 1606·2019-08-30 12:46
閱讀 1116·2019-08-30 10:51
閱讀 2418·2019-08-29 12:43