了解Javascript和node.js中的回调

Cem*_* K. 2 javascript callback node.js

我很长一段时间都是PHP(CodeIgniter和WordPress)开发人员,最近才想学习其他一些语言.我已经开始学习Ruby(在Rails和Sinatra上),Python(带有Flask框架)和带有node.js的Javascript.

我决定使用这些语言创建我能想到的最基本的应用程序,URL扩展器.我已经设法在每种语言中创建一个工作版本,除了node.js和Javascript.

我知道我的问题,我知道它与回调有关.我知道我做得不对.我得到了回调的基本概念,但我无法弄清楚如何修复我创建的这个混乱.

这是我的全部代码:

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();
Run Code Online (Sandbox Code Playgroud)

服务器启动,当发出请求时,它调用expand函数,该函数返回终端中的扩展URL.我试图让它在浏览器中打印.

任何帮助表示赞赏.提前致谢.

Ray*_*nos 6

你犯了一些瑕疵.

你应该重写expand来传递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);    
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,回调预计具有签名,(err, data)其中几乎所有节点中的回调都具有该签名.我们还添加了错误处理,这是必须的.

我们现在更改onRequest以实际调用expand

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我们添加了错误处理逻辑,并解压缩了从查询字符串扩展的实际URL.

通常doSomething<data, callback<err, result>>,node.js中的模式非常有效.

它与let result = doSomething<data> mayThrow err您在普通阻塞语言中所期望的完全相同,除非它是异步的.

请注意,将ServerResponse对象传递给函数的替代选项是不受欢迎的,这样做会在expand函数和服务器响应之间创建不必要的硬耦合.

expand函数应该只扩展一个url并返回扩展的url,它没有业务做IO本身.

完整代码