Javascript 使用http.get-in节点理解回调

Javascript 使用http.get-in节点理解回调,javascript,asynchronous,callback,Javascript,Asynchronous,Callback,这里是新的节点程序员,由于节点的异步性质,我很难理解如何从函数返回http请求的内容。这是我的程序的精简版本。 我所要做的就是1:创建一个函数,从一个站点获取数据(如果有必要,它是JSON和XML),2:能够从程序中的任何地方调用该函数,3:能够操作从函数中返回的任何数据 您放置(和调用)回调函数的方式让我头疼。我已经研究了几十个http.get示例和普通回调示例,但还没有找到一个示例可以像我的示例中那样将两者合并。经过几天的失败尝试,我觉得如果有人能在我的示例中演示如何做到这一点,它可能最终

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

我所要做的就是1:创建一个函数,从一个站点获取数据(如果有必要,它是JSON和XML),2:能够从程序中的任何地方调用该函数,3:能够操作从函数中返回的任何数据


您放置(和调用)回调函数的方式让我头疼。我已经研究了几十个http.get示例和普通回调示例,但还没有找到一个示例可以像我的示例中那样将两者合并。经过几天的失败尝试,我觉得如果有人能在我的示例中演示如何做到这一点,它可能最终会在我的大脑中发出咔哒声(祈祷)。

在数据有机会返回之前,您正在调用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);
}

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

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)
  })
})
您可能还希望查看流控制库,如(或基于my promise的),或通用promise库,如。 不过,我建议首先熟悉回调的基本知识

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


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

您想要一个延迟的(承诺也是一个延迟的)和
.then()
.when()
。js应该有文档(我不是节点开发人员,但这是Javascript中的常见模式)。编辑:谢谢你的建议。我从教程(包括您链接的教程)中了解到,Promise已从Node中删除。我不知道为什么,因为它看起来非常有用。然而,我觉得在我深入研究插件之前,我应该强迫自己理解回调(这是节点异步特性的一个重要部分);从Node.js中删除该实现是因为它没有得到很好的实现,而不是因为Node.js不“支持”延迟。这个可操作的术语留给了userland的一个练习,这意味着它将不是Node.js本机产品,但提供其功能的库仍然是可行和有用的。感谢您的建议。但问题是,我实际上不想调用console.log,我希望能够在函数之外操作数据(a和b),我只是把控制台放在那里作为一个例子,说明如何同时使用这两个变量。在您给出的示例中,假设我们替换了“console.log(body);”带有“返回体;”。什么样的语法允许它实际工作?@jwhazel,当您设计所描述的内容时(异步回调中的过程代码无法完成),您已经构建了一个(可能有限的)延迟或承诺。延迟模式或多或少地在依赖进程之间建立了一个共同的观察者,当回调返回到该对象并被观察到时,当可观察契约履行时(所有承诺履行或在设定的时间内以其他方式处理),另一个函数被调用,它合并或执行任何要求函数被观察为终止的操作。最后一行中的console.log将不起作用。也就是说,它不会记录任何内容,因为主体尚未填充。
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)
  })
})