問題描述
我無法理解 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 請求示例
- 對回調、承諾和如何做的解釋訪問異步返回的數據
這篇關于在完成函數本身的所有操作之前,Node 是否可以從函數調用中返回一個值?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!