javascript 用外行的术语理解异步代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11233633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding Asynchronous Code in Layman's terms
提问by PinkElephantsOnParade
I understand the basic thing about asynchronous-ness: things don't execute sequentially. And I understand there is something very powerful about that... allegedly. But for the life of me I can't wrap my head around the code. Let's take a look at async Node.JS code that I HAVE WRITTEN...but don't truly get.
我了解异步性的基本知识:事物不会按顺序执行。而且我知道有一些非常强大的东西......据称。但是对于我的生活,我无法将头围绕在代码上。让我们来看看我写过的异步 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();
}
Where did response come from again? postData? Why can't I define a variable in this "callback" and then use it outside of the callback? Is there a way to have a few things be sequential then the rest of the program async?
反应又是从哪里来的?发布数据?为什么我不能在这个“回调”中定义一个变量,然后在回调之外使用它?有没有办法让一些事情顺序然后程序的其余部分异步?
回答by Michelle Tilley
I'm not sure where this function is being used, but the point of callbacks is that you pass them into some function that runs asynchronously; it stores your callback away, and when that function is done with whatever it needs to do, it will callyour callback with the necessary parameters. An example from front-to-back is probably best.
我不确定这个函数在哪里使用,但回调的重点是你将它们传递给一些异步运行的函数;它存储你的回调,当该函数完成它需要做的任何事情时,它会用必要的参数调用你的回调。从前到后的例子可能是最好的。
Imagine we have a framework, and in it there is an operation that runs for a long time, fetching some data from the database.
想象一下,我们有一个框架,其中有一个运行很长时间的操作,从数据库中获取一些数据。
function getStuffFromDatabase() {
// this takes a long time
};
Since we don't want it to run synchronously, we'll allow the user to pass in a callback.
由于我们不希望它同步运行,我们将允许用户传入回调。
function getStuffFromDatabase(callback) {
// this takes a long time
};
We'll simulate taking a long time with a call to setTimeout
; we'll also pretend we got some data from the database, but we'll just hardcode a string value.
我们将模拟花费很长时间调用setTimeout
; 我们还会假设我们从数据库中获取了一些数据,但我们只会对字符串值进行硬编码。
function getStuffFromDatabase(callback) {
setTimeout(function() {
var results = "database data";
}, 5000);
};
Finally, once we have the data, we'll callthe callback given to us by the user of the framework's function.
最后,一旦我们有了数据,我们将调用框架函数的用户给我们的回调。
function getStuffFromDatabase(callback) {
setTimeout(function() {
var results = "database data";
callback(results);
}, 5000);
};
As a user of the framework, you'd do something like this to use the function:
作为该框架的用户,您可以执行以下操作来使用该函数:
getStuffFromDatabase(function(data) {
console.log("The database data is " + data);
});
So, as you can see data
(same as response
and postData
in your example) came from the function that you pass your callback into; it gives that data to you when it knows what that data should be.
所以,你可以看到data
(同response
和postData
在你的例子),从你通过回调函数来成; 当它知道该数据应该是什么时,它会向您提供该数据。
The reason you can't set a value in your callback and use it outside the callback is because the callback itself doesn't happen until later in time.
您不能在回调中设置值并在回调之外使用它的原因是因为回调本身直到稍后才会发生。
// 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
When the console.log
runs, the assignment of var results
hasn't happened yet!
当console.log
运行时,var results
尚未发生分配!
回答by Thinking Sites
You have several unrelated questions here:
您在这里有几个不相关的问题:
1) The power of async is being able to do multiple things at the same time without locking the main thread. In node and js in general, this applies particularly to ajax file requests. This means that I can fire off several async calls to retreive files, and not lock the main thread while it renders the content. My preferred framework is jQuery, which has convenient $.Deferred that wraps and standardizes async calls for jQuery usage.
1) async 的强大之处在于能够在不锁定主线程的情况下同时执行多项操作。通常在 node 和 js 中,这尤其适用于 ajax 文件请求。这意味着我可以触发多个异步调用来检索文件,并且在呈现内容时不会锁定主线程。我的首选框架是 jQuery,它有方便的 $.Deferred 包装和标准化异步调用以使用 jQuery。
2) response and postData come from the parent method. There's nothing magical here, it's a normal function call, so the values of these are created elsewhere and passed into this invocation. Depending on which node framework you have, the exact signature of your method will change.
2) response 和 postData 来自父方法。这里没有什么神奇的,它是一个普通的函数调用,所以这些值在别处创建并传递到这个调用中。根据您拥有的节点框架,您的方法的确切签名会发生变化。
3) You can define a global variable in your callback if it's properly scoped. It seem though that you need help learning what scope is. Here are some links
3) 如果范围适当,您可以在回调中定义全局变量。看来您需要帮助了解范围是什么。这里有一些链接
http://www.digital-web.com/articles/scope_in_javascript/
http://www.digital-web.com/articles/scope_in_javascript/
http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/
http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/
4) Once you go async, you can never go back, however, by leveraging promise and deferred objects like with jQuery Deferreds you can wait for several asyncs to complete before continuing your execution in yet another async. Deferreds are your friends.
4)一旦你进入异步,你就永远无法返回,但是,通过利用像 jQuery Deferreds 这样的承诺和延迟对象,你可以等待几个异步完成,然后再在另一个异步中继续执行。延期是你的朋友。
回答by handsomeransoms
Looks like you're working through the Node Beginner Book. I encourage you to work through the entire book, it really is an excellent introduction. If you are trying to understand Javascript better, Douglas Crockford's videos on YouTube are a great overview: 1, 2.
看起来您正在阅读Node Beginner Book。我鼓励你通读整本书,它确实是一个很好的介绍。如果您想更好地理解 Javascript,YouTube 上的 Douglas Crockford 视频是一个很好的概述:1, 2。
The piece of code you've posted doesn't have enough context for me to really help you. response
is a parameter that you're passing to your function, it does not come from postData. If you are working with code the way the Node Beginner Book suggests, you are probably passing response to your newuser function all the way down from the createServer function, which is part of the http module that comes with Node.
您发布的这段代码没有足够的上下文让我真正帮助您。response
是您传递给函数的参数,它不是来自 postData。如果您按照 Node Beginner Book 建议的方式使用代码,那么您可能会将响应从 createServer 函数一直传递到 newuser 函数,它是 Node 附带的 http 模块的一部分。
You can't define a variable in the callback and then use it in the callback because Javascript is lexically scoped. Here's a Stack Overflow poston the topic of Javascript's scope. The first video by Doug Crockford that I posted also has a great explanation of Javascript's scoping rules.
你不能在回调中定义一个变量,然后在回调中使用它,因为 Javascript 是词法范围的。这是关于 Javascript 范围主题的Stack Overflow 帖子。我发布的 Doug Crockford 的第一个视频也很好地解释了 Javascript 的范围规则。
Javascript isn't necessarily async. It simply provides anonymous functions that are closures, which are a useful tool for easily implementing async logic. Again, the Node Beginner Book shows a good example of writing synchronous code with Node (not what you want), then rewriting it to make it async.
Javascript 不一定是异步的。它只是提供了作为闭包的匿名函数,这是轻松实现异步逻辑的有用工具。同样,Node Beginner Book 展示了使用 Node 编写同步代码(不是你想要的)的一个很好的例子,然后重写它以使其异步。