【问题标题】:Understanding callbacks with http.get in node在节点中使用 http.get 理解回调
【发布时间】:2013-05-03 05:42:27
【问题描述】:

这里是新的节点程序员,由于节点的异步性质,我很难理解如何从函数返回 http 请求的内容。这是我的程序的精简版。

//#1
function getwebsite(url) {
    var body;
    http.get(url, function (res) {
        res.on('data', function (chunk) {
            body += chunk;
            //***Right here, I need 'body' returned out of this function***
        });
    });
}


//#2
var a = getwebsite('website1.com');
var b = getwebsite('website2.com');

//#3
console.log(a+b);

我想要做的就是 1:创建一个从站点获取数据的函数(如果重要的话,它的 JSON 和 XML),2:能够从我程序中的任何位置调用该函数,3:是能够操纵从我的函数返回的任何数据。

你应该放置(和调用)回调函数的方式让我很头疼。我研究了几十个 http.get 和一般回调示例的示例,但还没有找到一个像我的示例中那样合并的示例。经过几天的失败尝试,我觉得如果有人可以在我的示例中展示如何做到这一点,它可能最终会在我的大脑中点击(手指交叉)。

【问题讨论】:

  • 你想要一个 Deferred(Promise 也是 Deferred),以及 .then().when()。 Node.js 应该有文档(我不是 Node 开发人员,但这是 Javascript 中的常见模式)。编辑:You might try this tutorial.
  • 感谢您的建议。我对教程(包括您链接的教程)的理解是,Promise 已从 Node.js 中删除。我不知道为什么,因为它看起来非常有用。然而,我觉得在这一点上,我应该强迫自己理解回调(这是 Node 异步性质的重要组成部分),然后再深入研究插件。
  • 你没听懂在说什么;从 Node.js 中删除了实现因为它没有很好地实现,而不是因为 Node.js 不会“支持”延迟。可操作的术语留给用户空间练习意味着它不会是 Node.js 原生产品,但提供其功能的库仍然可行且有用。

标签: javascript asynchronous callback


【解决方案1】:

这是您要用于普通回调样式的基本模式:

function getwebsite(url, cb) {
    var body = "";
    http.get(url, function (res) {
        res.on('data', function (chunk) {
            body += chunk.toString();
            // you can't return a value from this function
            // the return value would be swallowed by the function
            // that is calling this function
            // which is not your code, but internal Node.js code
        });
        res.on("end", function() {
          cb(null, body)
        })
        res.on("error" function(error) {
          cb(error)
        })
    });
}

getwebsite("a", function(error, contentsA) {
  if (error) throw "Error getting website A."
  getwebsite("b", function(error, contentsB) {
    if (error) throw "Error getting website B."
    console.log(contentsA)
    console.log(contentsB)
  })
})

您可能还想研究像Async(或我的基于promise 的Faithful)这样的流控制库,或者像RSVP.js 这样的通用promise 库。 不过,我建议先熟悉回调的基础知识。

对于简单的 http 请求,使用request 模块要容易得多。然后,您不必绑定事件侦听器。你只有一个函数,你可以以与getwebsite 函数类似的方式使用它(这有问题!)。

要熟悉异步编程,您可能需要尝试使用fs.readFilefs.writeFile 读写一些文件。例如,尝试将文件 A 的内容写入文件 B。这些都是非常简单的函数,但您需要正确处理回调流。相比之下,Node 的 http 模块相对复杂。或者使用请求模块,正如我所提到的。

【讨论】:

    【解决方案2】:

    您在数据有机会返回之前调用了 console.log()。您可以将 body 变量带到更高的范围并附加到该范围内。即

    var body;
    
    function getwebsite(url) {
        http.get(url, function (res) {
    
            res.on('data', function (chunk) {
                body += chunk;
                //***Right here, I need 'body' returned out of this function***
                outputBody(body);
            });
        });
    }
    var a = getwebsite('website1.com');
    var b = getwebsite('website2.com');
    
    function outputBody(val){
        console.log(val);
    }
    

    【讨论】:

    • 感谢您的建议。但问题是我实际上并不想调用console.log,我希望能够在函数之外操作数据(a和b),我只是把控制台扔在那里作为我如何做的例子同时对这两个变量做一些事情。假设在您给出的示例中我们替换了 'console.log(body);'用'返回身体;'。允许它实际工作的语法是什么?
    • @jwhazel,当您设计所描述的内容时(异步回调中的过程代码无法做到这一点),您将构建一个(可能有限的)Deferred 或 Promise。 Deferred 模式或多或少在依赖进程之间建立了一个公共观察者,当回调返回到该对象并被观察时,当可观察的合同被履行(所有承诺在设定的时间内履行或以其他方式处理)时,另一个函数被称为合并或执行任何需要将函数观察为终止的操作。
    • 最后一行的console.log 不起作用。也就是说,它不会记录任何内容,因为 body 还没有被填充。
    猜你喜欢
    • 2013-04-06
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多