2012-06-27 39 views
18

我理解异步的基本原理:事情不会按顺序执行。据我所知,有一些非常强大的东西......据称。但是对于我来说,我无法将自己的头围绕在代码上。让我们来看看我写过的异步Node.JS代码...但是并没有真正得到。了解Layman的术语中的异步代码

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(); 
} 

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

回答

41

我不知道使用这个功能在哪里,但回调的一点是,要将其传递到运行异步一些功能;它将你的回调存储起来,当这个功能完成后,它将会用你需要的参数调用你的回调。从前到后的例子可能是最好的。

假设我们有一个框架,在它那里是很长一段时间运行,从数据库中获取一些数据的操作。

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); 
}); 

所以,你可以看到(在你的例子一样responsepostDatadata来自您将回调转换为的功能;它会在知道数据应该是什么时将这些数据提供给您。

你可以不设置在回调的值,并用它的回调以外的原因是因为回调本身不会发生,直到后来在时间。

// 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分配还没有发生!

+0

从技术角度而言,你是对的,但你错过的是“为什么你想首先做一个回调”。这就是让异步如此重要的原因。 – jcolebrand

+3

我不会说我不会再读这一两次 - 但这可能是最好的解释,没有在这里身体上,可以给,嘿。 – PinkElephantsOnParade

+1

我认为这是理解回调如何工作的很好的解释 - 谢谢! – wmock

6

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

1)异步电动机的功率是能够同时做多件事情没有锁定主线程。通常,在节点和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你可以等待几个异步操作,以在继续执行另一个异步之前完成。延期是你的朋友。

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

+0

不知何故错过了这个非常好的答案,我第一次看透:+1 – PinkElephantsOnParade

+0

该死的,你做对了。我真棒! –

+2

我鼓掌信心 – PinkElephantsOnParade

1

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

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

您不能在回调中定义一个变量,然后在回调中使用它,因为Javascript在词汇范围内。这里是关于Javascript范围的Stack Overflow post。 Doug Crockford发布的第一个视频也对JavaScript的范围规则做了很好的解释。

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