I have a formidable form which parse the request. Then along with this request is the file being uploaded.. In formidable you can listen to an event if there's a file.
我有一个强大的形式来解析请求。然后这个请求就是正在上传的文件。如果有文件,你可以收听一个事件。
var form = new formidable.IncomingForm({
uploadDir: __dirname + '/temp',
keepExtensions: true
});
This is where I will listen to the event
这是我将听取此事件的地方
form.on('file', function(name, file){
var file = file;
fs.readFile(file.path, readFileCallback);
});
function readFileCallback(err, contents){
console.log(file);
if (err) throw err;
....
}
My first code was a chain of callback functions and it's kind of hard to read and maintain so I switch with this approach where I would declare functions then call it as a callback instead of like this:
我的第一个代码是一系列回调函数,它有点难以阅读和维护所以我用这种方法切换,我会声明函数然后将其称为回调,而不是像这样:
form.on('file', function(name, file){
fs.readFile(file.path, function(err, contents){
console.log(file);
if (err) throw err;
....
});
});
With this kind of approach, I could access the outside variable which is file
. I'm wondering what is the difference between the two in accessing the outside variables. Thanks in advance.
通过这种方法,我可以访问外部变量file。我想知道两者在访问外部变量时有什么区别。提前致谢。
1 个解决方案
#1
1
It's a matter of scope. Code has access to the variables declared within the function, its containing function (if any), its containing function (if any), and so on, and then globals.
这是一个范围问题。代码可以访问函数内声明的变量,它包含的函数(如果有的话),它包含的函数(如果有的话),等等,然后是全局变量。
In your first example, readFileCallback
is declared outside the form.on
callback, and so it doesn't have access to things inside the form.on
callback.
在第一个示例中,readFileCallback在form.on回调之外声明,因此它无法访问form.on回调中的内容。
In your second example, the function is inside the form.on
callback, and so it does have access to the things inside it.
在第二个示例中,函数位于form.on回调中,因此它可以访问其中的内容。
Note that in the second example, in theory a new function is created each time the callback is called. That's fine, JavaScript engines are really fast at creating functions (and good ones will reuse the code even though a separate function object is created).
请注意,在第二个示例中,理论上每次调用回调时都会创建一个新函数。没关系,JavaScript引擎在创建函数方面非常快(即使创建了单独的函数对象,优秀的函数也会重用代码)。
Normally you want to create the function at the outermost location where it has access to everything it needs. So in your case, that would be inside form.on
, but outside the readFile
callback. Which is exactly where your second example has it. But you can use a named function like your first example if you like, just put it in form.on
's callback:
通常,您希望在最外面的位置创建该功能,以便能够访问所需的一切。所以在你的情况下,这将在form.on中,但在readFile回调之外。这正是你的第二个例子所在的地方。但是你可以使用像你的第一个例子那样的命名函数,只需将它放在form.on的回调中:
form.on('file', function(name, file){
fs.readFile(file.path, readFileCallback);
function readFileCallback(err, contents){
console.log(file);
if (err) throw err;
....
}
});
Let's take an example where everything had a simple name, and follow through two calls:
让我们举一个例子,其中一切都有一个简单的名称,并通过两个调用:
function outer(outerArg) {
function middle(middleArg) {
function inner(innerArg) {
console.log("innerArg = " + innerArg);
console.log("middleArg = " + middleArg);
console.log("outerArg = " + outerArg);
}
inner(middleArg.toLowerCase());
}
middle(outerArg.toUpperCase());
}
outer
contains middle
which contains inner
, and outer
calls middle
(and middle
calls inner
). A call:
outer包含中间,包含内部和外部调用中间(和中间调用内部)。一个电话:
outer("Test1");
-
outer
gets the arg"Test1"
- It calls
middle
with"TEST1"
- It calls
inner
with"test1"
-
inner
outputs:innerArg = test1 middleArg = TEST1 outerArg = Test1
外部获取arg“Test1”
它用“TEST1”调用中间
它用“test1”调用内部
内在输出: innerArg = test1 middleArg = TEST1 outerArg = Test1
So far, so simple, but it's more exciting than that: What if middle
returns a function that calls inner
, instead of calling it immediately, and outer
returns returns middle
's return value?
到目前为止,这么简单,但它比那更令人兴奋:如果中间返回一个调用内部的函数,而不是立即调用它,外部返回返回中间的返回值,该怎么办?
function outer(outerArg) {
function middle(middleArg) {
function inner(innerArg) {
console.log("innerArg = " + innerArg);
console.log("middleArg = " + middleArg);
console.log("outerArg = " + outerArg);
}
function caller() { // ***
inner(middleArg.toLowerCase()); // ***
} // ***
return caller; // ***
}
return middle(outerArg.toUpperCase()); // ***
}
Now, calling outer
doesn't have any output at all:
现在,调用outer根本没有任何输出:
var f = outer("Test2");
But then calling the function middle
returned (caller
) does:
但后来调用函数middle返回(调用者):
f();
Output:
innerArg = test2 middleArg = TEST2 outerArg = Test2
The arguments still exist after outer
and middle
return! But it's even more interesting:
外部和中间回归后,这些论点仍然存在!但它更有趣:
var f1 = outer("Test3");
var f2 = outer("Test4");
f2(); // Note -- calling the second one first
f1();
Output:
innerArg = test4 middleArg = TEST4 outerArg = Test4 innerArg = test3 middleArg = TEST3 outerArg = Test3
So that means, two outerArg
s still existed after both calls to outer
had finished, along with two middleArgs
. How?
这意味着,在两个外部调用完成后,两个outerArgs仍然存在,还有两个middleArgs。怎么样?
They exist on objects attached to the functions:
它们存在于附加到函数的对象上:
- Calling
outer
creates an execution context (an object), which amongst other things (and leaving out a lot of details) holds the arguments and local variables for that call toouter
. Let's call it the "outer context." It also has a reference to the execution context containing it (the global context, in our code). Normally that object gets cleaned up when a functon returns... - ...but
outer
creates a function,middle
. When you create a function, the current execution context is attached to the function. That's how it has access to the variables and such in that outer context. -
outer
callsmiddle
, creating an inner execution context, andmiddle
creates two other function (inner
andcaller
), which each get that inner context attached to them.middle
then returnscaller
, socaller
exists after the call tomiddle
completes. Sincecaller
has a reference to the inner execution context, the context continues to exist (just like any other object), even thoughmiddle
has returned. Since that context has a reference toinner
,inner
also continues to exist. -
outer
returns the return value ofmiddle
(which iscaller
), and so that meanscaller
still exists whenouter
returns, which means the inner context it refers to still exists, which meansinner
still exists, and the outer context still exists because the inner context has a reference to it.
调用外部会创建一个执行上下文(一个对象),除其他外(并省略很多细节)保存该外部调用的参数和局部变量。我们称之为“外部背景”。它还引用了包含它的执行上下文(我们的代码中的全局上下文)。通常,当一个功能返回时,该对象会被清理掉...
...但是外部创造了一个功能,中间。创建函数时,当前执行上下文将附加到函数。这就是它如何在外部环境中访问变量等。
外部调用中间,创建内部执行上下文,中间创建另外两个函数(内部和调用者),每个函数都附加到它们的内部上下文。中间然后返回调用者,因此调用中间完成后调用者存在。由于调用者具有对内部执行上下文的引用,因此上下文将继续存在(就像任何其他对象一样),即使中间已返回。既然那个上下文有内在的引用,内在也继续存在。
outer返回middle的返回值(也就是调用者),这意味着当外部返回时调用者仍然存在,这意味着它所引用的内部上下文仍然存在,这意味着内部仍然存在,并且外部上下文仍然存在,因为内部上下文有一个参考。
...which is how f1
and f2
have access to those arguments after outer
returns: When you run them, they look up the values in the contexts attached to them.
...在外部返回之后,f1和f2如何访问这些参数:当您运行它们时,它们会查找附加到它们的上下文中的值。
#1
1
It's a matter of scope. Code has access to the variables declared within the function, its containing function (if any), its containing function (if any), and so on, and then globals.
这是一个范围问题。代码可以访问函数内声明的变量,它包含的函数(如果有的话),它包含的函数(如果有的话),等等,然后是全局变量。
In your first example, readFileCallback
is declared outside the form.on
callback, and so it doesn't have access to things inside the form.on
callback.
在第一个示例中,readFileCallback在form.on回调之外声明,因此它无法访问form.on回调中的内容。
In your second example, the function is inside the form.on
callback, and so it does have access to the things inside it.
在第二个示例中,函数位于form.on回调中,因此它可以访问其中的内容。
Note that in the second example, in theory a new function is created each time the callback is called. That's fine, JavaScript engines are really fast at creating functions (and good ones will reuse the code even though a separate function object is created).
请注意,在第二个示例中,理论上每次调用回调时都会创建一个新函数。没关系,JavaScript引擎在创建函数方面非常快(即使创建了单独的函数对象,优秀的函数也会重用代码)。
Normally you want to create the function at the outermost location where it has access to everything it needs. So in your case, that would be inside form.on
, but outside the readFile
callback. Which is exactly where your second example has it. But you can use a named function like your first example if you like, just put it in form.on
's callback:
通常,您希望在最外面的位置创建该功能,以便能够访问所需的一切。所以在你的情况下,这将在form.on中,但在readFile回调之外。这正是你的第二个例子所在的地方。但是你可以使用像你的第一个例子那样的命名函数,只需将它放在form.on的回调中:
form.on('file', function(name, file){
fs.readFile(file.path, readFileCallback);
function readFileCallback(err, contents){
console.log(file);
if (err) throw err;
....
}
});
Let's take an example where everything had a simple name, and follow through two calls:
让我们举一个例子,其中一切都有一个简单的名称,并通过两个调用:
function outer(outerArg) {
function middle(middleArg) {
function inner(innerArg) {
console.log("innerArg = " + innerArg);
console.log("middleArg = " + middleArg);
console.log("outerArg = " + outerArg);
}
inner(middleArg.toLowerCase());
}
middle(outerArg.toUpperCase());
}
outer
contains middle
which contains inner
, and outer
calls middle
(and middle
calls inner
). A call:
outer包含中间,包含内部和外部调用中间(和中间调用内部)。一个电话:
outer("Test1");
-
outer
gets the arg"Test1"
- It calls
middle
with"TEST1"
- It calls
inner
with"test1"
-
inner
outputs:innerArg = test1 middleArg = TEST1 outerArg = Test1
外部获取arg“Test1”
它用“TEST1”调用中间
它用“test1”调用内部
内在输出: innerArg = test1 middleArg = TEST1 outerArg = Test1
So far, so simple, but it's more exciting than that: What if middle
returns a function that calls inner
, instead of calling it immediately, and outer
returns returns middle
's return value?
到目前为止,这么简单,但它比那更令人兴奋:如果中间返回一个调用内部的函数,而不是立即调用它,外部返回返回中间的返回值,该怎么办?
function outer(outerArg) {
function middle(middleArg) {
function inner(innerArg) {
console.log("innerArg = " + innerArg);
console.log("middleArg = " + middleArg);
console.log("outerArg = " + outerArg);
}
function caller() { // ***
inner(middleArg.toLowerCase()); // ***
} // ***
return caller; // ***
}
return middle(outerArg.toUpperCase()); // ***
}
Now, calling outer
doesn't have any output at all:
现在,调用outer根本没有任何输出:
var f = outer("Test2");
But then calling the function middle
returned (caller
) does:
但后来调用函数middle返回(调用者):
f();
Output:
innerArg = test2 middleArg = TEST2 outerArg = Test2
The arguments still exist after outer
and middle
return! But it's even more interesting:
外部和中间回归后,这些论点仍然存在!但它更有趣:
var f1 = outer("Test3");
var f2 = outer("Test4");
f2(); // Note -- calling the second one first
f1();
Output:
innerArg = test4 middleArg = TEST4 outerArg = Test4 innerArg = test3 middleArg = TEST3 outerArg = Test3
So that means, two outerArg
s still existed after both calls to outer
had finished, along with two middleArgs
. How?
这意味着,在两个外部调用完成后,两个outerArgs仍然存在,还有两个middleArgs。怎么样?
They exist on objects attached to the functions:
它们存在于附加到函数的对象上:
- Calling
outer
creates an execution context (an object), which amongst other things (and leaving out a lot of details) holds the arguments and local variables for that call toouter
. Let's call it the "outer context." It also has a reference to the execution context containing it (the global context, in our code). Normally that object gets cleaned up when a functon returns... - ...but
outer
creates a function,middle
. When you create a function, the current execution context is attached to the function. That's how it has access to the variables and such in that outer context. -
outer
callsmiddle
, creating an inner execution context, andmiddle
creates two other function (inner
andcaller
), which each get that inner context attached to them.middle
then returnscaller
, socaller
exists after the call tomiddle
completes. Sincecaller
has a reference to the inner execution context, the context continues to exist (just like any other object), even thoughmiddle
has returned. Since that context has a reference toinner
,inner
also continues to exist. -
outer
returns the return value ofmiddle
(which iscaller
), and so that meanscaller
still exists whenouter
returns, which means the inner context it refers to still exists, which meansinner
still exists, and the outer context still exists because the inner context has a reference to it.
调用外部会创建一个执行上下文(一个对象),除其他外(并省略很多细节)保存该外部调用的参数和局部变量。我们称之为“外部背景”。它还引用了包含它的执行上下文(我们的代码中的全局上下文)。通常,当一个功能返回时,该对象会被清理掉...
...但是外部创造了一个功能,中间。创建函数时,当前执行上下文将附加到函数。这就是它如何在外部环境中访问变量等。
外部调用中间,创建内部执行上下文,中间创建另外两个函数(内部和调用者),每个函数都附加到它们的内部上下文。中间然后返回调用者,因此调用中间完成后调用者存在。由于调用者具有对内部执行上下文的引用,因此上下文将继续存在(就像任何其他对象一样),即使中间已返回。既然那个上下文有内在的引用,内在也继续存在。
outer返回middle的返回值(也就是调用者),这意味着当外部返回时调用者仍然存在,这意味着它所引用的内部上下文仍然存在,这意味着内部仍然存在,并且外部上下文仍然存在,因为内部上下文有一个参考。
...which is how f1
and f2
have access to those arguments after outer
returns: When you run them, they look up the values in the contexts attached to them.
...在外部返回之后,f1和f2如何访问这些参数:当您运行它们时,它们会查找附加到它们的上下文中的值。