在完成函数本身的所有操作之前,Node 是否可以从函数调用中返回一个值?
我无法理解 Node 在并行处理和函数调用返回值方面的操作方式.
I'm having trouble understanding how Node operates regarding it's parallel processing and returning values from function calls.
仅供参考:下面的 gulp 函数仅作为此问题的示例而创建.
FYI: The gulp function below is merely created as an example for this question.
在Read a large file
语句完成处理(大文件已从文件系统完全读取并添加流)之前,该函数是否可能返回流,还是 Node 足够聪明,可以在返回之前完成所有语句?
Is it possible that the function could return the stream before the Read a large file
statement has finished processing (the large file has been fully read from the file system and the stream has been added), or is Node smart enough to complete all statements before returning?
function moveFiles(){
var gulp = require('gulp'),
stream = require('merge-stream')();
// Read a large file
stream.add(gulp.src('src/large-file.txt')
.pipe(gulp.dest('dest/'))
);
// Read a small file
stream.add(gulp.src('src/small-file.txt')
.pipe(gulp.dest('dest/'))
);
return (stream.isEmpty() ? null : stream);
}
推荐答案
在完成函数本身的所有操作之前,Node 是否可以从函数调用中返回一个值?
Could Node feasibly return a value from a function call before completing all operations within the function itself?
这是一个棘手的问题.答案是否定的,在某种程度上,返回一个值意味着函数已完成执行,它从堆栈中取回并且它永远不会再做任何事情 - 当然除非它在另一个时间被调用,但关键是这个特定的调用结束了.
This is a tricky question. The answer is no, in a way that returning a value means that the function is finished executing, it's taken back from the stack and it will never do anything again - unless it's invoked another time of course, but the point is that this particular invocation is over.
但棘手的部分是 函数 已完成执行,这并不意味着它不能安排将来发生其他事情.稍后会变得更复杂,但首先是一个非常简单的示例.
But the tricky part is that it's the function that's finished executing and it doesn't mean that it couldn't schedule something else to happen in the future. It will get more complicated in a minute but first a very simple example.
function x() {
setTimeout(function () {
console.log('x1'));
}, 2000);
console.log('x2');
return;
console.log('x3');
}
这里当你调用 x()
然后它会安排 another 函数在 2 秒后运行,然后它会打印 x2
然后它将返回 - 此时此函数无法再为该调用执行任何其他操作.
Here when you call x()
then it will schedule another function to run after 2 seconds, then it will print x2
and then it will return - at which point this function cannot do anything else ever again for that invocation.
这意味着 x3
永远不会被打印,但 x1
最终会被打印 - 因为它是另一个在超时触发时将被调用的函数.匿名函数将被调用不是因为 x()
函数在返回后可以做任何事情,而是因为它设法在返回之前安排了超时时间.
It means that x3
will never get printed, but x1
will eventually get printed - because it's another function that will be called when the timeout fires. The anonymous function will get called not because the x()
function can do anything after it returns, but because it managed to schedule the timeout before it returned.
现在,一个函数可以返回一个承诺,该承诺将在一段时间后得到解决,而不是仅仅安排未来发生的事情.例如:
Now, instead of just scheduling things to happen in the future, a function can return a promise that will get resolved some time later. For example:
function y() {
console.log('y1');
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('message from y()');
}, 2000);
});
console.log('y2');
}
现在,当你运行时:
var promise = y();
将会发生的是 y1
将被打印,一个新的承诺将被返回并且 y2
将永远不会被打印,因为此时 y()
返回并且不能做任何其他事情.但它设法安排了一个超时,将在两秒后解决这个承诺.
what will happen is that y1
will get printed, a new promise will get returned and y2
will never get printed because at that point y()
returned and cannot do anything else. But it managed to schedule a timeout that will resolve the promise after two seconds.
您可以通过以下方式观察它:
You can observe it with:
promise.then(function (value) {
console.log(value);
});
所以通过这个例子你可以看到,虽然 y()
函数本身返回并且不能做任何其他事情,但将来可以调用其他一些(在这种情况下是匿名的)函数并完成y()
函数已启动的作业.
So with this example you can see that while the y()
function itself returned and cannot do anything else, some other (anonymous in this case) function can be called in the future and finish the job that the y()
function has initiated.
所以我希望现在清楚为什么这是一个棘手的问题.在某种程度上,一个函数在返回后不能做任何事情.但它可以安排一些其他函数作为超时、事件处理程序等,这些函数可以在函数返回后执行某些操作.如果函数返回的东西是一个承诺,那么调用者可以很容易地在它准备好时观察到未来的值.
So I hope now it's clear why it's a tricky question. In a way a function cannot do anything after returning. But it could have scheduled some other functions as timeouts, event handlers etc. that can do something after the functions returns. And if the thing that the function returns is a promise then the caller can easily observe the value in the future when it's ready.
所有示例都可以通过使用箭头函数来简化,但我想明确指出这些都是单独的函数,其中一些是命名的,一些是匿名的.
All of the examples could be simplified by using the arrow functions but I wanted to make it explicit that those are all separate functions, some of them are named, some are anonymous.
有关更多详细信息,请参阅其中一些答案:
For more details see some of those answers:
- 详细说明如何使用回调和承诺
- 解释如何在复杂的请求处理程序
- 在AJAX 请求示例
- 对回调、承诺和如何做的解释访问异步返回的数据
相关文章