电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

在實例中重學JavaScript事件循環

瀏覽:88日期:2023-10-06 15:44:02

單線程的JS

眾所周知js是一門單線程語言,即同一時間只能做一件事。為什么js是單線程的呢,主要與它的用途有關。

作為瀏覽器腳本語言,js的主要用途是和用戶互動&操作DOM,我們并不想并行的操作DOM。如果不是單線程的話,我們一個線程在給DOM節點上添加內容,另一個線程卻刪除了這個節點,到底該以哪個為準呢?

所以為了避免復雜性,從一誕生,JavaScript 就是單線程。

事件循環(event loop)

JS是一門單線程語言,意味著代碼要一行一行的執行。所有任務都要排隊,前一個任務結束,才會執行后一個任務。

但平時大家開發時常用到的ajax,setTimeOut,promise之類的并沒有阻塞進程。如果瀏覽器只有一個js引擎構成,遇到上面這些比較耗時的請求或操作時,瀏覽器就會阻塞住,這肯定不是我們想要的。

其實js單線程是指瀏覽器在解釋和執行js代碼時只有一個線程,即js引擎線程。但瀏覽器還包括一些其他的線程來處理這些異步的方法,比如Web APIs線程,GUI渲染線程等。

事件循環的處理流程:

JS線程依靠調用棧來處理執行js代碼,當遇到一些異步的操作時,則將其移交給Web APIs,自己繼續往下進行。Web APIs線程則將收到的事件按一定的規則和順序添加到任務隊列里去。JS線程處理完當前所有任務(即執行棧為空),則去檢查任務隊列里是否有等待被處理的事件,若有,則取出一個事件回調放入執行棧中執行。然后不斷循環第三步。

宏任務與微任務

任務隊列又分為宏任務隊列和微任務隊列:

宏任務隊列(macrotask queue):存放的是setTimeout, setInterval, setImmediate, I/O, UI rendering等。 微任務隊列(microtask queue):存放的是Promises, Object.observe, MutationObserver,process.nextTick等。

所以我們細化一下事件循環的處理流程(瀏覽器環境):

JS線程依靠調用棧來處理執行js代碼,當遇到一些異步的操作時,則將其移交給Web APIs,自己繼續往下進行。Web APIs線程則將收到的事件按一定的規則和順序添加到任務隊列里去。宏任務事件則添加到宏任務隊列,微任務事件則添加到微任務隊列。JS線程處理完當前所有任務(即執行棧為空),會先去微任務隊列檢查是否有待處理的事件,若有,會將微任務隊列里的所有事件一件件執行完直到微任務隊列為空,再去宏任務隊列取出最前面的一個事件執行,執行完這一個宏任務事件后再去檢查微任務隊列是否有事件待處理。然后不斷循環第三步。

實際需求中重學JavaScript事件循環

什么是JS事件循環?

在秋招的時候經常會被問到這個問題,但自己的理解僅限于以上,然后刷過幾道輸出值順序的題目,沒有過業務中的實際應用場景。后來拿到offer后就忘的一干二凈了,直到畢業入職后開始寫代碼重新遇到了這才有了更深一步的理解。

背景用戶上傳多張圖片,前端拿到每張圖片的url和寬高發送給后端。

解決首先是拿到用戶上傳的文件,做一些校驗和限制

// 調用系統彈框添加圖片的方法addFile(e) { let uploadFiles = e.target.files,self = this; self.getListData = []; // 要傳給后端的對象數組 self.testFiles(uploadFiles) // 對用戶上傳的文件做一些校驗和限制 self.loadAll(uploadiles) // 調用loadAll方法},

然后讓我們看一下loadAll,主要是遍歷上傳的這些圖片文件,然后每一個圖片文件都調用了loadImg

loadAll(files) { let promises = [],self = this // 遍歷文件流 files.forEach((file,i) => { // 創建對象,push到數組里 (self.getListData).push({ imageUrl: ’’, }); let eachPromise = self.loadImg(file,i) // 存儲當前promise對象 promises.push(eachPromise) }) Promise.all(promises).then(() => { //全部完成,向后端發送請求 }).catch(err => { console.log(err) })},

然后讓我們看一下loadImg,這個方法返回一個Promise對象,主要是為了保證拿到圖片的URL以及在img.onload里拿到圖片的寬高,因為這兩個事件都是異步事件。

實際上js主線程是不會等待這兩個結果,就會繼續往下執行的。但因為我們在img.onload里才會把Promise給resolve出去,而loadAll方法里用了一個Promise.all來等待所有promise都完成,這樣就可以保證向后端發送請求時所有的圖片的url和寬高都能拿到。

loadImg(file,i) { return new Promise(async (resolve,reject) => { let self = this // 調用公司wos服務,拿圖片文件的url let successRes = await _fileUpload.uploadFile(item) if(successRes && successRes !== ’error’){ self.getListData[i][’imageUrl’] = successRes.url } let img = new Image() img.src = successRes.url img.onload = () => { self.getListData[i][’width’] = img.width self.getListData[i][’height’] = img.height resolve() } img.onerror = (e) => { reject(e) } })}

讓我們想一下如果把loadImg里拿圖片的url這個操作放到loadAll里呢?

loadAll(files) { let promises = [],self = this // 遍歷文件流 files.forEach(async(file,i) => { // 創建對象,push到數組里 (self.getListData).push({ imageUrl: ’’, }); // 調用公司wos服務,拿圖片文件的url let successRes = await _fileUpload.uploadFile(item) if(successRes && successRes !== ’error’){ self.getListData[i][’imageUrl’] = successRes.url } let eachPromise = self.loadImg(file,i) // 存儲當前promise對象 promises.push(eachPromise) }) Promise.all(promises).then(() => { //全部完成,向后端發送請求 }).catch(err => { console.log(err) })},

如果變成這種寫法,因為js的主線程執行棧不會等待await返回結果,循環里await _fileUpload.uploadFile(item)這行代碼后面的內容會被交給Web APIs然后跳出async函數。繼續執行主線程,而現在Promise.all的參數是一個空數組,然后就直接發了請求。但現在并沒有拿到圖片的URL和寬高。

關鍵字await只能使async函數一直等待,執行棧當然不可能停下來等待的,await將其后面的內容包裝成Promise交給Web APIs后,執行棧會跳出async函數繼續執行,直到Promise執行完并返回結果。await只在async函數里面奏效。

總結

從上面這個需求的實現中,好像對事件循環的理解更深刻了!像Promise.then里和await后面的代碼都會等待返回結果后再被放入對應事件的任務隊列中等待執行,JS線程會繼續向下執行調用棧。包括vue中的watch handler也是被先放入了任務隊列里等待。

所以可知事件循環在實際工作中對寫代碼和優化代碼都非常重要~如理解有誤請在評論區多多指教。

以上就是在實例中重學JavaScript事件循環的詳細內容,更多關于JavaScript 事件循環的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 衬四氟_衬氟储罐_四氟储罐-无锡市氟瑞特防腐科技有限公司 | 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 上海刑事律师|刑事辩护律师|专业刑事犯罪辩护律师免费咨询-[尤辰荣]金牌上海刑事律师团队 | 智能案卷柜_卷宗柜_钥匙柜_文件流转柜_装备柜_浙江福源智能科技有限公司 | 团建-拓展-拓展培训-拓展训练-户外拓展训练基地[无锡劲途] | 一路商机网-品牌招商加盟优选平台-加盟店排行榜平台 | 钢托盘,钢制托盘,立库钢托盘,金属托盘制造商_南京飞天金属制品实业有限公司 | 好物生环保网、环保论坛 - 环保人的学习交流平台 | 威实软件_软件定制开发_OA_OA办公系统_OA系统_办公自动化软件 | 散热器-电子散热器-型材散热器-电源散热片-镇江新区宏图电子散热片厂家 | 德国BOSCH电磁阀-德国HERION电磁阀-JOUCOMATIC电磁阀|乾拓百科 | 气密性检测仪_气密性检测设备_防水测试仪_密封测试仪-岳信仪器 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 电缆接头_防水接头_电缆防水接头_防水电缆接头_上海闵彬 | 北京印刷厂_北京印刷_北京印刷公司_北京印刷厂家_北京东爵盛世印刷有限公司 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 冷却塔风机厂家_静音冷却塔风机_冷却塔电机维修更换维修-广东特菱节能空调设备有限公司 | 太平洋亲子网_健康育儿 品质生活 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 304不锈钢无缝管_不锈钢管厂家 - 隆达钢业集团有限公司 | 999范文网_优质范文下载写作帮手| LED显示屏_LED屏方案设计精准报价专业安装丨四川诺显科技 | 品牌广告服务平台,好排名,好流量,好生意。 | 成都离婚律师|成都结婚律师|成都离婚财产分割律师|成都律师-成都离婚律师网 | 有机肥设备生产制造厂家,BB掺混肥搅拌机、复合肥设备生产线,有机肥料全部加工设备多少钱,对辊挤压造粒机,有机肥造粒设备 -- 郑州程翔重工机械有限公司 | 山东PE给水管厂家,山东双壁波纹管,山东钢带增强波纹管,山东PE穿线管,山东PE农田灌溉管,山东MPP电力保护套管-山东德诺塑业有限公司 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | 动物解剖台-成蚊接触筒-标本工具箱-负压实验台-北京哲成科技有限公司 | 安徽合肥项目申报咨询公司_安徽合肥高新企业项目申报_安徽省科技项目申报代理 | 全国冰箱|空调|洗衣机|热水器|燃气灶维修服务平台-百修家电 | 发电机价格|发电机组价格|柴油发电机价格|柴油发电机组价格网 | 微型驱动系统解决方案-深圳市兆威机电股份有限公司 | 清水混凝土修复_混凝土色差修复剂_混凝土色差调整剂_清水混凝土色差修复_河南天工 | 暴风影音| 代理记账_公司起名核名_公司注册_工商注册-睿婕实业有限公司 | 圆周直径尺-小孔内视镜-纤维研磨刷-东莞市高腾达精密工具 | 劳动法网-专业的劳动法和劳动争议仲裁服务网 | 水稻烘干机,小麦烘干机,大豆烘干机,玉米烘干机,粮食烘干机_巩义市锦华粮食烘干机械制造有限公司 水环真空泵厂家,2bv真空泵,2be真空泵-淄博真空设备厂 | 海外仓系统|国际货代系统|退货换标系统|WMS仓储系统|海豚云 | 河南中整光饰机械有限公司-抛光机,去毛刺抛光机,精密镜面抛光机,全自动抛光机械设备 | 耳模扫描仪-定制耳机设计软件-DLP打印机-asiga打印机-fitshape「飞特西普」 |