良い質問だと思います。まず、Javascript の非同期プログラミングの構造を覚えて頂く必要があります。少し長くなります。
言語を問わず、プログラムがネットワークで通信する、ファイルを読む、データベースを読むなど外の世界へアクセスするときは、処理に時間がかかる場合があり、実行を開始すると終了するまで待つ必要があります。javascript 以外の言語では、外部へアクセスするライブラリを呼び出すと、結果が返されます。これは外部へのアクセスを開始してから終了するまで一時的にプログラムを停止して待ち、結果を受け取って返すことで実現されています。
javascript はシングルスレッドで動く仕様となっており、プログラムの実行を止めて待つと、すべての処理が止まってしまい性能が出ません。そこで、アクセスを開始する命令を出した後、終わったときに関数を呼び出してもらうという方法で続きの処理を実行します。たとえば、ファイルから読み出すときは、
javascript
1var fs = require('fs');
2function test() {
3 fs.readFile('./test.txt', 'utf8', function (err, text) {
4 console.log('end.');
5 console.log(text);
6 });
7 console.log('start.');
8}
9test();
のように書きますが、test関数から fs.readFile 関数を呼び出して、その呼出が終わった時点では、コールバックは呼び出されていません。いつ呼び出されるかというと、コンソールに'start.'を印刷して test() の実行が終わった後です。他にも外部へのアクセスをした結果を待っているものがあれば、早いもの順でコールバックが呼び出されます。このコールバック関数は Javascript の処理系から呼び出されるので、プログラマの書いたコードから呼び出されるものではありません。
さて、上記の例でファイルを読み出した後の処理はすべてコールバック関数の中で実行しなければならないことに注意してください。すると、test()関数の中でプログラムの続きの処理を全部記述しなければならなくなり、サブルーチン化、モジュール化がまったくできなくなってしまいます。そこで、サブルーチンにコールバックを渡して、続きの処理を呼び出し側で記述できるようにします。例えば、
javascript
1var fs = require('fs');
2function test(done) {
3 fs.readFile('./test.txt', 'utf8', function (err, text) {
4 console.log('end.');
5 done(text)
6 });
7 console.log('start.');
8}
9
10test(function (text) {
11 console.log(text);
12});
のように修正することで、 test() 関数はファイルを読み出し、その続きの処理(ここでは、コンソールにファイルの内容を印刷する)は呼び出し側に記述できるようになりました。
Javascript では、他のモジュールの関数を呼び出すと、いつ非同期が呼び出されるのかわからないので、常にこの作法に従う必要があります。
passport もこの作法に従っているわけです。function(user, done) {done(null, user.id);});
は他の言語なら function(user) {return user.id;});
となるところですが、上記のマナーにしたがって、返却値ではなく、コールバック関数の引数で値を返しているわけです。
例にあげてもらったコードですと、コールバックの中に非同期処理が含まれておらず、コールバック関数が呼ばれるとすぐに done を呼ぶことになるので、なぜ返却値で返さないのかわからないと思います。シリアライズやデシリアライズの処理中に外部へのアクセス(例えばデータベースへのアクセス)が途中で必要になる場合にどう記述するか考えていただければ、なぜ、このような構造になっていることがわかるかと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/10/05 23:06
2016/10/06 03:12