非同步是javascript的精髓

ghostwu發表於2018-07-07

最近做了一個智慧家居的APP,目前純JS程式碼已經4000多行,不包括任何引入的庫。還在不斷升級改造中。。。這個專案到處都是非同步。大多數都是3~4層呼叫。給我的感覺就是非同步當你習慣了,你會發現很爽。下面舉個最簡單的例子? 

你知道怎麼返回一個非同步呼叫的值嗎? 

也許你會這麼幹 

            function getValue(){
                var a = 10;
                setTimeout( function(){
                    a += 10;
                }, 10 );    
                return a;
            }

你肯定得不到你想要的20

            function test(){
                var res = getValue();
                return res;
            }

console.log( test() );  //結果10

為什麼?

因為settimeout的原因,把a += 10放在佇列中,等所有的同步程式碼完成之後,才輪到他執行。所以return的時候,這個a += 10 是沒有執行的,而且你也不知道,非同步到底什麼時候完成? 這個是不確定的,哪怕你設定了10ms,未必是10ms。。。。如果佇列前面有耗時較長的其他任務,10ms還是得不到響應。。。這樣的例子太多了。比如,我最近的專案,控制空調的關和開。。很顯然,這個時間受制於網路和晶片,以及空調的響應。。並不是設定了多長時間,就是那個時間返回。

那不知道他什麼時候,返回,怎麼拿到他的值?

用回撥!

            function getValue2( fn ){
                var a = 10;
                setTimeout( function(){
                    a += 10;
                    fn && fn( a );
                }, 10 );    
                return a;
            }
            function test2(){
                getValue2( function( res ){
                    console.log( res );
                } );
            }

test2();

你GET到了嗎?

下面就是一個簡單的非同步呼叫了:

var Q = {
        a : [],
        in : function( v ){
            if( !/number|function/.test( typeof( v ) ) ) return;
            this.a.push( v );
            return this;
        },
        out : function(){
            var me = this;
            var v = me.a.shift();
            if( !v ) return;
            if( typeof( v ) == `function` ) {
                v();
                me.out();
                return;
            }
            setTimeout( function(){
                me.out();
            }, v );
        }
    }

    function watch( res ){
        var oDiv = document.createElement( "div" );
        oDiv.innerHTML = res;
        // console.log( res );
        document.body.appendChild( oDiv );
    }

    Q.in( function(){
        watch( "1 <strong style=`color:red`>延時3秒 -->輸出2</strong>" );
    })
    .in( 3000 )
    .in( function(){
        watch( "2 <strong style=`color:green`>延時2秒 -->輸出2</strong>" );
    } )
    .in( 2000 )
    .in( function(){
        watch( "3 <strong style=`color:blue`>後面沒有了</strong>" );
    } ).out();

 

相關文章