2011-12-18 16 views
2

をNode.jsのは、私は最近、いくつかの他の言語を学びたいと思っ長い時間PHP(CodeIgniterの&ワードプレス)開発者です。 Ruby(Rails、Sinatra)、Python(Flaskフレームワーク)、Javascript(node.js)を学びました。理解JavaScriptでコールバックと

私は、これらの言語のそれぞれを使用して、私は考えることができる最も基本的なアプリケーション、URLエキスパンダを作成することを決めました。私は、node.jsとJavascriptを除いて、あらゆる言語で動作するバージョンを作成することができました。

私はちょっと私の問題を知って、私はそれがコールバックに関連している知っています。私はそれを正しくしていないことを知っている。私はコールバックの基本的な考え方を得ますが、私が作成したこの混乱を修正する方法を理解することはできません。

これは私のwhole code

var http = require('http'); 
var url = require('url'); 
function expand() { 
    var short = url.parse('http://t.co/wbDrgquZ'); 
    var options = { 
     host: short.hostname, 
     port: 80, 
     path: short.pathname 
    }; 
    function longURL(response) { 
     console.log(response.headers.location); 
    } 
    http.get(options, longURL); 
} 

function start() { 
    function onRequest(request, response) { 
     console.log("Request received."); 
     response.writeHead(200, { 
      "Content-Type": "text/plain" 
     }); 
     response.write("Hello World"); 
     expand(); 
     response.end(); 
    } 
    http.createServer(onRequest).listen(8888); 
    console.log("Server has started."); 
} 
start(); 

サーバが起動し、要求が行われたときに、それは、端末に展開URLを返す拡張関数を呼び出します。私はそれをブラウザで印刷しようとしています。

何か助けていただければ幸いです。前もって感謝します。

答えて

6

あなたは、いくつかの欠陥を作りました。

URLを渡してコールバックを渡すには、展開を書き直す必要があります。非同期の処理を行う関数のノードには、通常、(data, callback)というシグネチャがあります。これは、基本的には、私はこの関数が何かをして、それが完了したら教えてほしいと言うことができます。ここ

function expand(urlToParse, callback) { 
    // note we pass in the url this time 
    var short = url.parse(urlToParse); 
    var options = { 
     host: short.hostname, 
     port: 80, 
     path: short.pathname 
    }; 
    // note we store the clientRequest object temporarily 
    var clientRequest = http.get(options, extractRealURL); 

    // Always attach the error handler and forward any errors 
    clientRequest.on("error", forwardError); 

    function extractRealURL(res) { 
     callback(null, res.headers.location);  
    } 

    function forwardError(error) { 
     callback(err);  
    } 
} 

コールバックは、ノード内のほぼ全てのコールバックが有する(err, data)の署名を有することが期待されます。また、エラー処理を追加する必要があります。

我々は今、実際にここで適切に

function onRequest(request, response) { 
    // parse the incoming url. true flag unpacks the query string 
    var parsedUrl = url.parse(request.url, true), 
     // extract the querystring url. 
     // http://localhost:8888/?url=http://t.co/wbDrgquZ 
     urlToExpand = parsedUrl.query.url; 

    // call expand with the url and a callback 
    expand(urlToExpand, writeResponse); 

    function writeResponse(error, newUrl) { 
     // handle the error case properly 
     if (error) { 
      response.writeHead(500, { 'Content-Type': 'text/plain'}); 
      // early return to avoid an else block 
      return response.end(error.message); 
     } 
     response.writeHead(200, { 'Content-Type': 'text/plain'}); 
     // write the new url to the response 
     response.end(newUrl); 
    } 
} 

を拡大呼び出すためにonRequestを変更我々は、ロジックエラー処理を追加しても、クエリ文字列から拡大する実際のURLを展開しています。

通常、doSomething<data, callback<err, result>>のパターンは、node.jsで非常にうまく機能します。

これは、非同期以外の通常のブロック言語で期待しているのと全く同じです(let result = doSomething<data> mayThrow err)。

ServerResponseオブジェクトを関数に渡す代替オプションは、展開関数とサーバーレスポンスの間に不必要なハード結合を作成することによって悩まされることに注意してください。

拡張機能はURLを展開して展開されたURLだけを返す必要があります.IO自体をやっているビジネスはありません。

Full code

+0

このコードは、urlパラメータを入力しないと失敗します。 'expand(urlToExpand、writeResponse);の呼び出しを続ける前に' parsedUrl.query.url'が定義されているかどうかをチェックする必要があります。 – Wavesailor

3

コールバックは、我々は呼び出すためのそのほかのコードのためにいくつかの他のコードに渡す機能を記述するためだけの言葉です。

例では、onRequestは、要求が受信されるたびに呼び出されるようにcreateServerに渡されるコールバック関数です。

あなたは、expand()が、onRequest関数がアクセスできるすべての同じ変数/パラメータへのアクセスを期待していると思います。これは当てはまりません。

あなたはexpand()responseオブジェクトを渡す必要があります。 expandへの呼び出しがhttp.getコールのための新しいコールバックlongURLを作成するので、それはあなたが渡されたresponseオブジェクトにアクセスする必要があります。

function expand(resp) { 
    // receive the original response object, and end the response when ready 
    var short = url.parse('http://t.co/wbDrgquZ'); 
    var options = { 
     host: short.hostname, 
     port: 80, 
     path: short.pathname 
    }; 
    function longURL(response) { 
     console.log(response.headers.location); 
     resp.end(response.headers.location); // end the original response 
    } 
    http.get(options, longURL); 
} 

function start() { 
    function onRequest(request, response) { 
     console.log("Request received."); 
     response.writeHead(200, { 
      "Content-Type": "text/plain" 
     }); 
     response.write("Hello World"); 
     expand(response); // pass this response object to expand 
    } 
    http.createServer(onRequest).listen(8888); 
    console.log("Server has started."); 
} 
0

をあなたが展開する関数にパラメータとして応答を送信していませんでしたまた、あなたが何かを書くことができる拡張()関数の前Response.Endの()を呼んでいた、ここでは修正バージョンです:

var http = require('http'); 
var url = require('url'); 

function expand(res) { 

    var short = url.parse('http://t.co/wbDrgquZ'); 

    var options = { 
    host: short.hostname, 
    port: 80, 
    path: short.pathname 
    }; 

    function longURL(response){ 
    console.log(response.headers.location); 
    res.end("<br />" + response.headers.location); 
    } 

    http.get(options, longURL); 

} 


function start() { 
    function onRequest(request, response) { 
    console.log("Request received."); 
    response.writeHead(200, {"Content-Type": "text/html"}); 
    response.write("Hello World"); 

    expand(response); 
    } 

    http.createServer(onRequest).listen(8888); 
    console.log("Server has started."); 
} 


start(); 
関連する問題