Javascript非同步編程

來源:互聯網
上載者:User

標籤:attach   handle   文法   之間   版本   請求   listen   note   trigger   


1、什麼是非同步(Asynchronous)編程?

    相對於同步(Synchronous)而言,非同步就是後一個任務不需要等待前一個任務結束就執行,而前一個任務結束以後執行回呼函數。

    最常見的非同步編程有setTimeout函數、 ajax請求等。

    如:

        for (var i = 1; i <= 3; i++) {
            setTimeout(function(){
                console.log("#",i);
            }, 0);
            console.log("*",i);
        };

    輸出的結果是:*1 *2 *3 #4 #4 #4

    涉及到的知識點: 非同步、閉包、範圍

    setTimeout是一個註冊事件,在主程式運行結束前,是不會調用的。

    就像為某個div綁定一個點擊事件一樣,在沒點擊之前,這個事件是不會被觸發的。

    這就是一個常見的非同步編程的例子。


2、非同步編程的方法

    Ⅰ、回呼函數

        假設有 f1(); f2(); 兩個函數,其中f2()在等待f1()的執行結果。

        function f1(f2){
            setTimeout(function(){
              f2();
            }, 1000);
          }

        代碼執行順序:f1(f2);

        優點:f1不會堵塞程式運行,相當於先執行程式的主要邏輯,將耗時的操作延遲執行
        缺點:不利於代碼的閱讀和維護,各個部分之間高度耦合(Coupling),而且每個任務只能指定一個回呼函數
            
    Ⅱ、事件監聽

        f1.on(‘done‘, f2);//jQuery寫法,當f1發生done事件,就執行f2

        function f1(){
        setTimeout(function () {
          f1.trigger(‘done‘);//執行完成後,立即觸發done事件
        }, 1000);
      }

        優點:可以綁定多個事件,每個事件可以指定多個回呼函數,而且可以"去耦合"(Decoupling),有利於實現模組化
        缺點:整個程式都要變成事件驅動型,運行流程會變得很不清晰


    Ⅲ、發布/訂閱

        jQuery.subscribe("done", f2);//f2向jQuery訂閱"done"訊號

        function f1(){
       setTimeout(function () {
         jQuery.publish("done");//f1執行完成後,向jQuery發布"done"訊號,從而引發f2的執行
       }, 1000);
     }


    Ⅳ、Promises對象   

        它的思想是,每一個非同步任務返回一個Promise對象,該對象有一個then方法,允許指定回呼函數。比如,f1的回呼函數f2,可以寫成:

        f1().then(f2);

        對f1進行如下改寫:

        function f1(){
       var dfd = $.Deferred();
       setTimeout(function () {
         dfd.resolve();
       }, 500);
       return dfd.promise;
     }

        優點:回呼函數變成了鏈式寫法,程式的流程可以看得很清楚,可以指定多個回呼函數,如:

             f1().then(f2).then(f3);
             f1().then(f2).fail(f3);

        缺點:編寫和理解,都相對比較難    

附幾個概念:

一、事件

    事件就是文檔或瀏覽器視窗中發生的一些特定的互動瞬間。

二、註冊事件
    
    註冊事件分為屬性註冊和方法註冊。

    屬性註冊:1.內嵌在DOM結構裡的屬性賦值

                HTML: <button onclick="sayHello()">點擊</button>

                  JS: function sayHello() {
                             console.log(‘hello‘)
                      }

            2.通過JS來指定元素對象的屬性賦值

                document.body.onclick = function (e) {
                    alert("為body註冊一個點擊事件");
                };

    方法註冊:1.通過addEventListener()方法註冊

                說明:在JS中,window、document、HtmlElement等對象可以通過addEventListener()方法註冊事件的處理常式。

                文法:EventTarget.addEventListener(eventName, eventHandler, |useCapture )

                參數:

                    ①eventName {string} :所要註冊的事件名稱,不區分大小寫。此名稱不需要像註冊事件屬性那樣首碼加上"on"。如註冊滑鼠點擊事件,寫為click。

                    ②eventHandler {function | function Object} :函數或者函數對象。事件觸發時所需要執行的函數;當使用函數對象多次註冊同一事件時,只當註冊一遍。

                    ③useCapture {boolean} 可選 :是否處於捕獲階段,預設為false。

            多次註冊:addEventListener()方法能為同一個對象的同一事件註冊多次。當發生此事件時,註冊的處理事件程式將按照註冊先後順序執行。

               注意:

                    ①IE9之前的IE的不支援此方法,可使用attachEvent()代替。

                    ②若使用相同的事件處理常式對象多次註冊在同一個事件上,只算註冊一次。

              例:

                      document.body.addEventListener(‘click‘,function(e){
                         console.log(‘被點擊一‘);
                    });
                             
                    document.body.addEventListener(‘click‘,function(e){
                        console.log(‘被點擊二‘);
                    });
                    
                    document.body.click(); // 輸出: 被點擊一 被點擊二

            2.通過attachEvent()方法註冊

              說明:IE9之前的IE版本可通過此方法註冊事件。

              文法:EventTarget.attachEvent(eventName, eventHandler)
              
                      ①eventName {string} :所要註冊的事件名稱,區分大小寫。這裡的名稱跟事件屬性一樣,以"on"開頭,後面跟著事件名稱。如:onclick、onload。
                      
                      ②eventHandler {function | function Object} :函數或者函數對象。事件觸發時所需要執行的函數;當使用函數對象多次註冊同一事件時,可註冊多次(addEventListener()方法只當註冊一次)。
              
          多次註冊:attachEvent()方法能為同一個對象的同一事件註冊多次。當觸發此事件時,也會依次執行。

             例:

                  function sayHellow(){
                   console.log(‘hello‘);
                }
                document.body.attachEvent(‘onclick‘,sayHellow);
                document.body.attachEvent(‘onclick‘,sayHellow); // sayHellow第二次註冊同一事件
                document.body.click(); //輸出2次sayHellow函數 :hello hello

二、登出事件

        JS中,可調用removeEventListener()[登出addEventListener()] 和 detachEvent()[登出attachEvent()] 來登出元素的某個事件指定的處理常式,也可以給事件屬性賦值null來登出此事件的所有綁定。
    
        1.removeEventListener(eventName, function Object)
        
        說明:登出通過addEventListener()註冊的事件處理常式。
    
        文法:EventTarget.removeEventListener(eventName, eventHandlerObj)
        
        參數:
        
            ①eventName {string} :所要登出的事件名稱,不區分大小寫。此名稱不需要像註冊事件屬性那樣首碼加上"on"。如註冊滑鼠點擊事件,寫為click。
            
            ②eventHandlerObj {function Object} :函數對象。傳入一個函數體是沒有效果的。
    
        例:
            
            // 登出body click事件的sayHello函數
            document.body.removeEventListener(‘click‘,sayHello);

        2.detachEvent(eventName, function Object)

            說明:登出通過attachEvent()註冊的事件處理常式。

            文法:EventTarget.detachEvent(eventName, eventHandlerObj)
            
            參數:
            
                ①eventName {string} :所要登出的事件名稱,區分大小寫。這裡的名稱跟事件屬性一樣,以"on"開頭,後面跟著事件名稱。如:onclick、onload。
                
                ②eventHandlerObj {function Object} ::函數對象。傳入一個函數體是沒有效果的。


           例:

                   // 登出body click事件的sayHello函數
                   document.body.detachEvent(‘onclick‘, sayHello);

        3.取消事件

            給對象的事件屬性賦值為null,可取消此事件的所有註冊過的處理事件程式。

            例:

                // onclick屬性賦值為null,相當於登出了onclick事件
                document.body.onclick=null;


參考連結:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
                http://www.qdfuns.com/notes/17398/e8a1ce8f863e8b5abb530069b388a158/page/.html


    

Javascript非同步編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.