用外行的术语理解异步代码

IT技术 javascript node.js asynchronous
2021-01-20 10:38:01

我了解异步性的基本知识:事物不会按顺序执行。而且我知道有一些非常强大的东西......据称。但是对于我的生活,我无法将头围绕在代码上。让我们来看看我写过的异步 Node.JS 代码……但并没有真正理解。

function newuser(response, postData) {
    console.log("Request handler 'newuser' was called.");
    var body = '<html>' + 
        '<head>' +
        '<meta http-equiv="Content-Type" content="text/html; ' +
        'charset=UTF-8" />' +
        '</head>' +
        '<body>' +
        '<form action=" /thanks" method="post">' +
        '<h1> First Name </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<h1> Last Name </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<h1> Email </h1>' +
        '<textarea name="text" rows="1" cols="20"></textarea>' +
        '<input type="submit" value="Submit text" />' +
        '</body>' +
        '</html>';
    response.writeHead(200, { "Content-Type": "text/html" });
    response.write(body);
    response.end();
}

react又是从哪里来的?发布数据?为什么我不能在这个“回调”中定义一个变量,然后在回调之外使用它?有没有办法让一些事情顺序然后程序的其余部分异步?

3个回答

我不确定这个函数在哪里使用,但回调的重点是你将它们传递给一些异步运行的函数;它存储你的回调,当该函数完成它需要做的任何事情时,它会用必要的参数调用你的回调。从前到后的例子可能是最好的。

想象一下,我们有一个框架,其中有一个运行很长时间的操作,从数据库中获取一些数据。

function getStuffFromDatabase() {
  // this takes a long time
};

由于我们不希望它同步运行,我们将允许用户传入回调。

function getStuffFromDatabase(callback) {
  // this takes a long time
};

我们将模拟花费很长时间调用setTimeout; 我们还会假设我们从数据库中获取了一些数据,但我们只会对字符串值进行硬编码。

function getStuffFromDatabase(callback) {
  setTimeout(function() {
    var results = "database data";
  }, 5000);
};

最后,一旦我们有了数据,我们将调用框架函数的用户给我们的回调。

function getStuffFromDatabase(callback) {
  setTimeout(function() {
    var results = "database data";
    callback(results);
  }, 5000);
};

作为该框架的用户,您可以执行以下操作来使用该函数:

getStuffFromDatabase(function(data) {
  console.log("The database data is " + data);
});

所以,你可以看到data(同responsepostData在你的例子),从你通过回调函数来; 当它知道该数据应该是什么时,它会向您提供该数据。

您不能在回调中设置值并在回调之外使用它的原因是因为回调本身直到稍后才会发生。

//  executed immediately  executed sometime in the future
//      |                  |       by getStuffFromDatabase
//      v                  v
getStuffFromDatabase(function(data) {
  var results = data; // <- this isn't available until sometime in the future!
});

console.log(results); // <- executed immediately

console.log运行时,var results尚未发生分配

我不会说我不会再读一两次了——但这可能是一个人不在现场的情况下可以给出的最好解释,呵呵。
2021-03-18 10:38:01
从技术角度来看,您是对的,但您错过的是“为什么要首先进行回调”。这就是使异步如此重要的原因。
2021-04-02 10:38:01
我认为这是理解回调如何工作的一个很好的解释 - 谢谢!
2021-04-02 10:38:01

您在这里有几个不相关的问题:

1) async 的强大之处在于能够在不锁定主线程的情况下同时执行多项操作。通常在 node 和 js 中,这尤其适用于 ajax 文件请求。这意味着我可以触发多个异步调用来检索文件,并且在呈现内容时不会锁定主线程。我的首选框架是 jQuery,它有方便的 $.Deferred 包装和标准化异步调用以使用 jQuery。

2) response 和 postData 来自父方法。这里没有什么神奇的,它是一个普通的函数调用,所以这些值在别处创建并传递到这个调用中。根据您拥有的节点框架,您的方法的确切签名会发生变化。

3) 如果范围适当,您可以在回调中定义全局变量。看来您需要帮助了解范围是什么。这里有一些链接

http://www.digital-web.com/articles/scope_in_javascript/

http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/

4)一旦你进入异步,你就永远无法返回,但是,通过利用像 jQuery Deferreds 这样的Promise和延迟对象,你可以等待几个异步完成,然后再在另一个异步中继续执行。延期是你的朋友。

http://api.jquery.com/category/deferred-object/

不知何故,我第一次浏览时错过了这个非常好的答案:+1
2021-04-12 10:38:01

看起来您正在阅读Node Beginner Book我鼓励你通读整本书,它确实是一个很好的介绍。如果您想更好地理解 Javascript,YouTube 上的 Douglas Crockford 视频是一个很好的概述:1 , 2

您发布的这段代码没有足够的上下文让我真正帮助您。response是您传递给函数的参数,它不是来自 postData。如果您按照 Node Beginner Book 建议的方式使用代码,那么您可能会将响应从 createServer 函数一直传递到 newuser 函数,它是 Node 附带的 http module的一部分。

你不能在回调中定义一个变量,然后在回调中使用它,因为 Javascript 是词法范围的。这是关于 Javascript 范围主题的Stack Overflow 帖子我发布的 Doug Crockford 的第一个视频也很好地解释了 Javascript 的范围规则。

Javascript 不一定是异步的。它只是提供了作为闭包的匿名函数,这是轻松实现异步逻辑的有用工具。同样,Node Beginner Book 展示了使用 Node 编写同步代码(不是你想要的)的一个很好的例子,然后重写它以使其异步。