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 裡最重要的東西 – 事件