js中的同步異步

「同步」  「異步」 這個詞平時見到的很頻繁,感受一直出如今平時的生活中,可是沒怎麼用過,寫代碼的時候也不多往這上面去考慮。前端

第一次看到 「同步」 「異步」 是寒假寫小程序的時候, 有一個方法當時特地用的同步(小程序不少方法都分爲同步和異步兩種 可能由於比較敏感把)。編程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  onCollectionTap: function (event) {
 
    var postsCollected = wx.getStorageSync('posts_collected');
    var postCollected = postsCollected[this.data.currentPostId];
    postCollected = !postCollected;
    //取反操做 讓收藏變成未收藏 爲收藏變成收藏
    postsCollected[this.data.currentPostId] = postCollected;
    //更新文章 是否 的緩存值
 
    // wx.showToast({
    //   title: postCollected?'收藏成功':"取消成功",
    //   duration: 900,
    //   icon:"success"
    this.showToast(postsCollected, postCollected);
  },

 

 這個是從本地獲取緩存數據,看這篇文章是否被我收藏了(由於沒有後臺記錄 是動態的綁定數據 因此要這樣作去避免刷新以後以前的收藏就沒了)  那麼我去獲取那個我用來標記是否以前收藏過的變量時,就得是一個同步的方法。  那麼這個時候就要思考  同步和異步是什麼, 何時應該用哪種。小程序

就這個問題 我當時問過一個學長,他當時給我解釋的意思,大概就是看 這件事情 重不重要 對於我進程影響大不大 去考慮用同步好 仍是異步好  。 舉個看的不少的例子。  關於點單這個問題瀏覽器

平時買奶茶,可能先去點個單,跟人家說 我要一杯觀音鐵奶,好,而後這個時候你想去旁邊的文具店逛一逛文具,看看有啥書想看的想買的。由於我已經買單了,我能夠先去作別的事情了 那麼我不須要坐在那裏等待,由於我不必一直等着人家作好 而後拿着奶茶去逛文具店,這對我不是那麼重要,我徹底能夠先作別的事情 過會回來拿。因此這就是異步了,我已經買單,那麼我不打算等待,老闆作奶茶這件事情我不是很關心,因此我能夠同時作一些別的事情,彷佛這個時候兩件事情是一塊兒作的。(後面會提出個人一點疑問) 那接着我在文具店了,誒,這個時候我我想買一本柯南,可是書架上最新的柯南賣完了,我不知道我是否看過最新本的,我必須等着老闆幫我找庫存,而後拿出來,我再肯定我是否要買(這是假設我必定要等着這件事情,我很關心 很看重,跟買奶茶不同)那麼這個過程就是同步的。緩存

 

 

Javascript語言是一門單線程的語言網絡

 單線程和異步確實不能同時成爲一個語言的特性。js選擇了成爲單線程的語言,因此它自己不多是異步的,多線程

可是你想啊,瀏覽器只分配給js一個主線程,用來執行那些函數,一次只能執行一個,這些任務造成一個任務隊列排隊等候執行,但前端的某些任務是很是耗時的(我以前也說過,有的時候 前端沒寫好,,實際上是能夠當黑客的 把人家電腦卡死),好比網絡請求,定時器(定時器必定要記得清啊! 我以前寫像素鳥的時候  那個管子不停的生成 雖然會清理 可是我把頁面就放那裏 無論它 可能 過一會 它就本身積累了一堆的管子在那裏  特別嚇人 )和事件監聽,若是讓他們和別的任務同樣,都老老實實的排隊等待執行的話,執行效率會很是的低,甚至致使頁面的假死。因此,瀏覽器爲這些耗時任務開闢了另外的線程,主要包括http請求線程,瀏覽器定時觸發器,瀏覽器事件觸發線程,這些任務是異步的。下圖說明了瀏覽器的主要線程。那js的宿主環境(瀏覽器)就很顯而易見的能夠看出來是多線程了把,因而 爲了解決js的這些嚴重問題  ,宿主環境經過某種方式(事件驅動,下文會講)使得js具有了異步的屬性 ,異步


這就是js的神奇地方  我的以爲計算機有意思就是由於有不少神奇的機智的地方async

單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。若是前一個任務耗時很長,後一個任務就不得不一直等着。因而就有一個概念——任務隊列。若是排隊是由於計算量大,CPU忙不過來,倒也算了,可是不少時候CPU是閒着的,由於IO設備(輸入輸出設備)很慢(好比Ajax操做從網絡讀取數據),不得不等着結果出來,再往下執行。因而JavaScript語言的設計者意識到,這時主線程徹底能夠無論IO設備,掛起處於等待中的任務,先運行排在後面的任務。等到IO設備返回告終果,再回過頭,把掛起的任務繼續執行下去。異步編程

因而,全部任務能夠分紅兩種,一種是同步任務(synchronous),另外一種是異步任務(asynchronous)。同步任務指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,只有等主線程任務執行完畢,"任務隊列"開始通知主線程,請求執行任務,該任務纔會進入主線程執行。

具體來講,異步運行機制以下:

(1)全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。
(2)主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
(3)一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。
(4)主線程不斷重複上面的第三步。

 

這個時候我看到第二,三條我就在想 按它文字邏輯,就成了我把那些函數放在任務隊列,等我有空了再去執行那個函數,若是我一開始就決定最後作那件事情 就變得跟同步沒啥區別了

開始各類查資料 先貼一些別人博客的描述

 

異步和多線程有什麼區別?其實,異步是目的,而多線程是實現這個目的的方法。異步是說,A發起一個操做後(通常都是比較耗時的操做,若是不耗時的操做就沒有必要異步了),能夠繼續自顧自的處理它本身的事兒,不用幹等着這個耗時操做返回。.Net中的這種異步編程模型,就簡化了多線程編程,咱們甚至都不用去關心Thread類,就能夠作一個異步操做出來。

 

異步操做的本質

  全部的程序最終都會由計算機硬件來執行,因此爲了更好的理解異步操做的本質,咱們有必要了解一下它的硬件基礎。 熟悉電腦硬件的朋友確定對DMA這個詞不陌生,硬盤、光驅的技術規格中都有明確DMA的模式指標,其實網卡、聲卡、顯卡也是有DMA功能的。DMA就是直 接內存訪問的意思,也就是說,擁有DMA功能的硬件在和內存進行數據交換的時候能夠不消耗CPU資源。只要CPU在發起數據傳輸時發送一個指令,硬件就開 始本身和內存交換數據,在傳輸完成以後硬件會觸發一箇中斷來通知操做完成。這些無須消耗CPU時間的I/O操做正是異步操做的硬件基礎。因此即便在DOS 這樣的單進程(並且無線程概念)系統中也一樣能夠發起異步的DMA操做。

 

異步調用並非要減小線程的開銷, 它的主要目的是讓調用方法的主線程不須要同步等待在這個函數調用上, 從而可讓主線程繼續執行它下面的代碼.與此同時, 系統會經過從ThreadPool中取一個線程來執行,幫助咱們將咱們要寫/讀的數據發送到網卡.因爲不須要咱們等待, 咱們等於同時作了兩件事情. 這個效果跟本身另外啓動一個線程來執行等待方式的寫操做是同樣的.可是, 異步線程能夠利用操做系統/.Net的線程池, 系統能夠根據吞吐量動態的管理線程池的大小.

=======================================================================
異步與多線程,從辯證關係上來看,異步和多線程並不時一個同等關係,異步是目的,多線程只是咱們實現異步的一個手段.什麼是異步:異步是當一個調用請求發送給被調用者,而調用者不用等待其結果的返回.實現異步能夠採用多線程技術或則交給另外的進程來處理

 

 

看了這麼多以後 我彷佛有點懂了 ,再返回去看 前面提到的  IO設備(輸入輸出設備) 和 CPU    哇就以爲本身好蠢...  差點就想爲了這件事情去問斌哥  還好還好 我選擇了本身思考 

再來捋一遍,爲何會卡呢  由於 IO太慢了啊  而IO跟cpu沒有衝突啊...  我徹底可讓它慢慢輸入輸出  而後我本身先去執行別的  好比我先去逛逛文具店  因此 其實兩件事情確實是同時在發生的,可是並無佔着一個線程,因此不叫多線程,本質上依舊是單線程   再看一眼那一大段引用的關於異步操做的本質的文字   擁有DMA功能的硬件在和內存進行數據交換的時候能夠不消耗CPU資源  因此一點都不衝突。 【我對計算機的這些東西有一些盲點,,因此也不知道理解的是否正確 】

 

 

 以上是針對於一些數據讀取異步過程的一個處理  可是像定時器,感受好像 應該不是這樣 因而去查了一下  還有一個東西叫  Web Worker

Web Worker 的做用,就是爲 JavaScript 創造多線程環境,容許主線程建立 Worker 線程,將一些任務分配給後者運行。在主線程運行的同時,Worker 線程在後臺運行,二者互不干擾。等到 Worker 線程完成計算任務,再把結果返回給主線程。這樣的好處是,一些計算密集型或高延遲的任務,被 Worker 線程負擔了,主線程(一般負責 UI 交互)就會很流暢,不會被阻塞或拖慢。

Worker 線程一旦新建成功,就會始終運行,不會被主線程上的活動(好比用戶點擊按鈕、提交表單)打斷。這樣有利於隨時響應主線程的通訊。可是,這也形成了 Worker 比較耗費資源,不該該過分使用,並且一旦使用完畢,就應該關閉。

Web Worker 有如下幾個使用注意點。

(1)同源限制

分配給 Worker 線程運行的腳本文件,必須與主線程的腳本文件同源。

(2)DOM 限制

Worker 線程所在的全局對象,與主線程不同,沒法讀取主線程所在網頁的 DOM 對象,也沒法使用documentwindowparent這些對象。可是,Worker 線程能夠navigator對象和location對象。

(3)通訊聯繫

Worker 線程和主線程不在同一個上下文環境,它們不能直接通訊,必須經過消息完成。

(4)腳本限制

Worker 線程不能執行alert()方法和confirm()方法,但可使用 XMLHttpRequest 對象發出 AJAX 請求。

(5)文件限制

Worker 線程沒法讀取本地文件,即不能打開本機的文件系統(file://),它所加載的腳本,必須來自網絡。

 

 

 

 

 

 

 

最後一個環節,再來看幾個關於異步的一些題目(更新中...  demo還沒徹底弄好)

 

 

 

 

 

-------~~~  (  回調函數使用很少,因此等之後詳細用過以後再來寫博客  )   ~~~-------

 

 

-------~~~   to be continued ~~~-------

相關文章
相關標籤/搜索