最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在實(shí)例中重學(xué)JavaScript事件循環(huán)

 更新時(shí)間:2020年12月03日 09:50:55   作者:ninger  
這篇文章主要介紹了在實(shí)例中重學(xué)JavaScript事件循環(huán),幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下

單線程的JS

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

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

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

事件循環(huán)(event loop)

JS是一門單線程語言,意味著代碼要一行一行的執(zhí)行。所有任務(wù)都要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。

但平時(shí)大家開發(fā)時(shí)常用到的ajax,setTimeOut,promise之類的并沒有阻塞進(jìn)程。如果瀏覽器只有一個(gè)js引擎構(gòu)成,遇到上面這些比較耗時(shí)的請(qǐng)求或操作時(shí),瀏覽器就會(huì)阻塞住,這肯定不是我們想要的。

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

事件循環(huán)的處理流程:

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

宏任務(wù)與微任務(wù)

任務(wù)隊(duì)列又分為宏任務(wù)隊(duì)列和微任務(wù)隊(duì)列:

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

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

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

實(shí)際需求中重學(xué)JavaScript事件循環(huán)

什么是JS事件循環(huán)?

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

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

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

// 調(diào)用系統(tǒng)彈框添加圖片的方法
addFile(e) {
 let uploadFiles = e.target.files,self = this;

 self.getListData = []; // 要傳給后端的對(duì)象數(shù)組

 self.testFiles(uploadFiles) // 對(duì)用戶上傳的文件做一些校驗(yàn)和限制
  
 self.loadAll(uploadiles) // 調(diào)用loadAll方法
},

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

loadAll(files) {
 let promises = [],self = this
 
 // 遍歷文件流
 files.forEach((file,i) => {
  // 創(chuàng)建對(duì)象,push到數(shù)組里
  (self.getListData).push({
   imageUrl: '', 
  });
  
  let eachPromise = self.loadImg(file,i)
  // 存儲(chǔ)當(dāng)前promise對(duì)象
  promises.push(eachPromise)
 })
 
 Promise.all(promises).then(() => {
  //全部完成,向后端發(fā)送請(qǐng)求
 }).catch(err => {
  console.log(err)
 })
},

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

實(shí)際上js主線程是不會(huì)等待這兩個(gè)結(jié)果,就會(huì)繼續(xù)往下執(zhí)行的。但因?yàn)槲覀冊(cè)趇mg.onload里才會(huì)把Promise給resolve出去,而loadAll方法里用了一個(gè)Promise.all來等待所有promise都完成,這樣就可以保證向后端發(fā)送請(qǐng)求時(shí)所有的圖片的url和寬高都能拿到。

loadImg(file,i) {
 return new Promise(async (resolve,reject) => {
  let self = this
  // 調(diào)用公司wos服務(wù),拿圖片文件的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這個(gè)操作放到loadAll里呢?

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

如果變成這種寫法,因?yàn)閖s的主線程執(zhí)行棧不會(huì)等待await返回結(jié)果,循環(huán)里await _fileUpload.uploadFile(item)這行代碼后面的內(nèi)容會(huì)被交給Web APIs然后跳出async函數(shù)。繼續(xù)執(zhí)行主線程,而現(xiàn)在Promise.all的參數(shù)是一個(gè)空數(shù)組,然后就直接發(fā)了請(qǐng)求。但現(xiàn)在并沒有拿到圖片的URL和寬高。

關(guān)鍵字await只能使async函數(shù)一直等待,執(zhí)行棧當(dāng)然不可能停下來等待的,await將其后面的內(nèi)容包裝成Promise交給Web APIs后,執(zhí)行棧會(huì)跳出async函數(shù)繼續(xù)執(zhí)行,直到Promise執(zhí)行完并返回結(jié)果。await只在async函數(shù)里面奏效。

總結(jié)

從上面這個(gè)需求的實(shí)現(xiàn)中,好像對(duì)事件循環(huán)的理解更深刻了!像Promise.then里和await后面的代碼都會(huì)等待返回結(jié)果后再被放入對(duì)應(yīng)事件的任務(wù)隊(duì)列中等待執(zhí)行,JS線程會(huì)繼續(xù)向下執(zhí)行調(diào)用棧。包括vue中的watch handler也是被先放入了任務(wù)隊(duì)列里等待。

所以可知事件循環(huán)在實(shí)際工作中對(duì)寫代碼和優(yōu)化代碼都非常重要~如理解有誤請(qǐng)?jiān)谠u(píng)論區(qū)多多指教。

以上就是在實(shí)例中重學(xué)JavaScript事件循環(huán)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 事件循環(huán)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JsChart組件使用詳解

    JsChart組件使用詳解

    JSChart能夠在網(wǎng)頁上生成圖標(biāo),常用于統(tǒng)計(jì)信息,十分好用的一個(gè)JS組件。這篇文章主要介紹了JsChart組件使用詳解,需要的朋友可以參考下
    2018-03-03
  • JavaScript中style.left與offsetLeft的使用及區(qū)別詳解

    JavaScript中style.left與offsetLeft的使用及區(qū)別詳解

    這篇文章主要介紹了JavaScript中style.left與offsetLeft的使用及區(qū)別詳解的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 學(xué)好js,這些js函數(shù)概念一定要知道【推薦】

    學(xué)好js,這些js函數(shù)概念一定要知道【推薦】

    本文主要介紹了一些js函數(shù)概念,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • 用JavaScript做一個(gè)簡(jiǎn)易計(jì)算器的三種方法舉例

    用JavaScript做一個(gè)簡(jiǎn)易計(jì)算器的三種方法舉例

    這篇文章主要給大家介紹了關(guān)于用JavaScript做一個(gè)簡(jiǎn)易計(jì)算器的三種方法,JS中實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器并不困難,我們只需利用基本的數(shù)學(xué)運(yùn)算符和JavaScript的語法即可,需要的朋友可以參考下
    2023-10-10
  • JS CSS文章查看系統(tǒng)

    JS CSS文章查看系統(tǒng)

    自己寫了個(gè)JS+CSS的小東西,用來看提升用戶體驗(yàn)的。 Name:WindowsTextShow;
    2008-12-12
  • JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能(防止刷新倒計(jì)時(shí)失效)

    JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能(防止刷新倒計(jì)時(shí)失效)

    這篇文章主要介紹了JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能防止刷新倒計(jì)時(shí)失效問題,在項(xiàng)目開發(fā)中經(jīng)常會(huì)用到此功能,下面小編通過本文給大家分享JS實(shí)現(xiàn)發(fā)送短信驗(yàn)證后按鈕倒計(jì)時(shí)功能(防止刷新倒計(jì)時(shí)失效),需要的朋友參考下吧
    2017-07-07
  • Uniapp實(shí)現(xiàn)下拉刷新的三種方式

    Uniapp實(shí)現(xiàn)下拉刷新的三種方式

    在小程序、h5等地方中,常常會(huì)用到下拉刷新這個(gè)功能,今天來講解實(shí)現(xiàn)這個(gè)功能的三種方式:全局下拉刷新,組件局部下拉刷新,嵌套組件下拉刷新,,文中通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • JSON與XML的區(qū)別對(duì)比及案例應(yīng)用

    JSON與XML的區(qū)別對(duì)比及案例應(yīng)用

    這篇文章主要介紹了JSON與XML的區(qū)別對(duì)比及案例應(yīng)用的講解。本文涉及到XML和JSON優(yōu)缺點(diǎn)講解及對(duì)比,非常不錯(cuò),具有一定的參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-11-11
  • JS中for...in?和?for...of?的區(qū)別解析

    JS中for...in?和?for...of?的區(qū)別解析

    for?…?in?用于迭代對(duì)象的可枚舉字符串屬性,包括自身屬性和繼承的屬性,但不會(huì)遍歷對(duì)象的原型鏈上的?非可枚舉屬性,以及對(duì)象的方法,這篇文章主要介紹了JS中for...in?和?for...of?的區(qū)別,需要的朋友可以參考下
    2024-03-03
  • Javascript中異步等待的深入理解

    Javascript中異步等待的深入理解

    Async / Await是人們期待已久的JavaScript功能,它使使用異步功能更加有趣和易于理解。這篇文章主要給大家介紹了關(guān)于Javascript中異步等待的相關(guān)資料,需要的朋友可以參考下
    2021-05-05

最新評(píng)論

徐闻县| 辉县市| 景泰县| 句容市| 安徽省| 博兴县| 尉犁县| 卓资县| 壤塘县| 澎湖县| 崇明县| 石首市| 贵港市| 称多县| 贵德县| 台北市| 威远县| 原阳县| 微山县| 盐城市| 沈阳市| 运城市| 南皮县| 万山特区| 和静县| 普兰县| 和田县| 潢川县| 新巴尔虎左旗| 勐海县| 石阡县| 巩义市| 行唐县| 固始县| 玛纳斯县| 阿克苏市| 梅州市| 湟源县| 阳曲县| 彭泽县| 鄂温|