Callback 到底是什麼呢? 當一個函式執行完畢後所執行的那個函式就是所謂的 callback 函式. 聽起來滿饒舌的齁. 一般來說如果你想讓 do_b 在 do_a 之後執行程式大概會長得這個樣子
function do_a(){
console.log( '`do_a`: 這會先出現');
}
function do_b(){
console.log( '`do_b`: 跟著才是這個' );
}
do_a();
do_b();
結果
`do_a`: 這會先出現 `do_b`: 跟著才是這個
但是因為 javascript 是一個事件驅動的語言. 所以如果當 do_a 所花的時間比 do_b 久的話, do_b 的結果就會比 do_a 早出來.
function do_a(){
// 模擬一個需要長間的 function
setTimeout( function(){
console.log( '`do_a`: 這個需要的時間比 `do_b` 長' );
}, 1000 );
}
function do_b(){
console.log( '`do_b`: 這本來應該出現在 `do_a` 之後但是卻先出現了' );
}
do_a();
do_b();
結果
`do_b`: 這本來應該出現在 `do_a` 之後但是卻先出現了 `do_a`: 這個需要的時間比 `do_b` 長
所以我們要怎麼確定讓 do_b 出現在 do_a 之後呢? 這時候 callbacks 就派上用場了.
function do_a( callback ){
setTimeout( function(){
// 模擬一個需要長間的 function
console.log( '`do_a`: 這個需要的時間比 `do_b` 長' );
// 如果 callback 存在的話就執行他
callback && callback();
}, 3000 );
}
function do_b(){
console.log( '`do_b`: 現在我們就可以肯定 `do_b` 出現在 `do_a` 之後了' );
}
do_a( function(){
do_b();
});
結果
`do_a`: 這個需要的時間比 `do_b` 長 `do_b`: 現在我們就可以肯定 `do_b` 出現在 `do_a` 之後了
各種不同套用 callback 的方式
function basic( callback ){
console.log( '作些事情' );
var result = '我是等會要被傳送給 `do something` 的 callback 的函式結果';
// 如果 callback 存在的話就執行他
callback && callback( result );
}
function callbacks_with_call( arg1, arg2, callback ){
console.log( '作些事情' );
var result1 = arg1.replace( 'argument', 'result' ),
result2 = arg2.replace( 'argument', 'result' );
this.data = '這等會可以讓 callback 函式用 `this` 來調用';
// 如果 callback 存在的話就執行他
callback && callback.call( this, result1, result2 );
}
// 這個和 `callbacks_with_call` 很相像
// 唯一不同點是將 `call` 換成了 `apply`
// 所以參數只能傳陣列
function callbacks_with_apply( arg1, arg2, callback ){
console.log( '作些事情' );
var result1 = arg1.replace( 'argument', 'result' ),
result2 = arg2.replace( 'argument', 'result' );
this.data = '這等會可以讓 callback 函式用 `this` 來調用';
// 如果 callback 存在的話就執行他
callback && callback.apply( this, [ result1, result2 ]);
}
basic( function( result ){
console.log( '這個 callback 函式會在 terminal 上列出 `basic` 函式執行的結果' );
console.log( result );
});
console.log( '--------------------------------------------------------------------------------------' );
( function(){
var arg1 = '我是 argument1',
arg2 = '我是 argument2';
callbacks_with_call( arg1, arg2, function( result1, result2 ){
console.log( '這一個 callback 函式將會列出 `callbacks_with_call` 的執行結果' );
console.log( 'result1: ' + result1 );
console.log( 'result2: ' + result2 );
console.log( 'data from `callbacks_with_call`: ' + this.data );
});
})();
console.log( '--------------------------------------------------------------------------------------' );
( function(){
var arg1 = '我是 argument1',
arg2 = '我是 argument2';
callbacks_with_apply( arg1, arg2, function( result1, result2 ){
console.log( '這一個 callback 函式將會列出 `callbacks_with_apply` 的執行結果' );
console.log( 'result1: ' + result1 );
console.log( 'result2: ' + result2 );
console.log( 'data from `callbacks_with_apply`: ' + this.data );
});
})();
結果
作些事情 這個 callback 函式會在 terminal 上列出 `basic` 函式執行的結果 我是等會要被傳送給 `do something` 的 callback 的函式結果 -------------------------------------------------------------------------------------- 作些事情 這一個 callback 函式將會列出 `callbacks_with_call` 的執行結果 result1: i am result1 result2: i am result2 data from `callbacks_with_call`: 這等會可以讓 callback 函式用 `this` 來調用 -------------------------------------------------------------------------------------- 作些事情 這一個 callback 函式將會列出 `callbacks_with_apply` 的執行結果 result1: i am result1 result2: i am result2 data from `callbacks_with_apply`: 這等會可以讓 callback 函式用 `this` 來調用
現在我們知道如何執行 node.js 的程式, 如何使用 require 和 exports, function scopes 以及 closures 還有 callbacks 的重要性. 接下來我們來看看 node.js 裡最重要的東西 – 事件




