[API-d15] - [Javascript 番外篇] Javascript callback, event
2014-10-15 00:00
2 minutes read

這幾天會探討 javascript 的特性,由於比較少在寫 js ,因此有錯請指正

javascript 有個特性:event

意思就是說,javascript 中,所有的事情都是由事件驅動的

如果說有寫過 web 前端的話,

其實呼叫 button.click function 時

並不會馬上執行 click 裡面的動作

而是加了一個 click 的 listener

等到 button 被 click 後,才會執行 click 裡面的程式碼

所以寫習慣一般 procedure 的程式會有點不太習慣

舉個 procedure 的例子,下面有五件事想要做:

煮飯(); // 10 分鐘

接電話(); // 1 分鐘

吃麵(); // 5 分鐘

丟垃圾(); // 7 分鐘

一般的程式會是照順序執行

也就是 煮飯完 -> 接電話 -> 吃麵 -> 丟垃圾

總執行時間 = 23 分鐘

但是如果把這段 code 丟給 javascript 執行的話

煮飯(); // 10 分鐘

接電話(); // 1 分鐘

吃麵(); // 5 分鐘

丟垃圾(); // 7 分鐘

就變成同時做煮飯,接電話,吃麵,丟垃圾了!

為了要預防這件事,有些事情還是有順序性的,

因此就要使用到 javascript callback 的特性

煮飯(function() {
	吃飯(function() {
		接電話(function() {
			丟垃圾();
		});
	});
});

意思就是煮飯完吃飯,吃完飯接電話,接完電話丟垃圾

以下有一個範例:

function wash() {
    setTimeout(function() {
        console.log("wash");
    }, 1000);
}

function eat() {
    setTimeout(function() {
        console.log("eat");
    }, 5000);
}

function running() {
    setTimeout(function() {
        console.log("running");
    }, 3000);
}

function doHouseWork() {
    wash();
    eat();
    running();
}

doHouseWork();

做家事執行了三件事,wash, eat, 和 running

其中每件事都設定不同的完成時間

以 procedure 的程式執行方式來看,在這邊用 ruby 舉例:

def wash
  sleep 1
  puts "wash"
end 

def eat
  sleep 5
  puts "eat"
end 

def running 
  sleep 3
  puts "running"
end 

def doHouseWork 
  wash
  eat
  running
end 

doHouseWork

是會 wash 1 秒後,接著 eat 5 秒,再 running 3 秒

所以總共是 9 秒

output 的順序會是:

wash // 1 秒
eat // 5 秒
running // 3 秒

但是在 javascript 中,output 的順序卻是:

wash // 1 秒
running // 3 秒
eat // 5 秒

所以總長度是 5 秒

那今天假設想要讓 javascript 有順序性時該怎麼辦?

拿上面的例子作修改的話:

function wash(callback) {
    setTimeout(function() {
        console.log("wash");
        callback.call();
    }, 1000);
}

function eat(callback) {
    setTimeout(function() {
        console.log("eat");
        callback.call();
    }, 5000);
}

function running() {
    setTimeout(function() {
        console.log("running");
    }, 3000);
}

function doHouseWork(callback) {
    console.log("doing house work");
    callback.call();
}

doHouseWork(function(){
    wash(function() {
        eat(function() {
            running();
        });
    });
});

很不錯的特性,但是也要特別對於這種特性作處理

有個 lib 很好用,async.js 來源

下回待續!


Back to posts


comments powered by Disqus