node.js - nodejs异步编程变量传递的问题。
PHP中文网
PHP中文网 2017-04-17 14:29:24
0
3
613
for(var i = 0; i < res.length;i++){
                
                var info = res[i];
                var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
                
                dlog(fpath);//位置1
                
                nodeRequire('fs').exists(fpath, function (exists) {
                    
                    dlog(fpath);//位置2
                });    
}                
                    

这段代码没贴全。
大致的作用就是从数据库里面循环读取附件列表,然后根据每个附件的信息,路径,去判断这个附件的文件是否存在。

现在的问题是,位置2得到的fpath变量永远都是同一个。
也就是说,外层的fpath无法正确的传递到位置2。因为异步执行的原因。如何解决这个问题呢?

PHP中文网
PHP中文网

认证0级讲师

reply all(3)
PHPzhong

Reason

You didn’t ask the reason but let me tell you the reason.

The fpath variable is just a variable (reference), and the callback function you pass only knows: "Oh, I can get the value of (reference) fpath then".

The key is that when you pass the function, what you pass is only an unexecuted function. There is a variable called fpath in the function. Since it has not been executed, the current value is not obtained.

When the asynchronous function is about to get it, the value of fpath is already the last one.

Solution

Suppose the question is:

var a = [1,2,3,4,5,6,8]

for (var i = 0; i < a.length; i++) {
  var c = a[i]
  setTimeout(function(){
    console.info(c);
  }, 100)
}

Solution 1: (Original solution)
The solution is also very simple. As mentioned above, the function was not executed at that time. We can create a function to execute part of it and use another (new function) variable to store it.

var a = [1,2,3,4,5,6,8]

for (var i = 0; i < a.length; i++) {
  var c = a[i]
  ;(function(c){
    setTimeout(function(){
      console.info(c);
    }, 100)
  })(c)
}

Solution 2: (es6 solution)

var a = [1,2,3,4,5,6,8]

for (var i = 0; i < a.length; i++) {
  let c = a[i]
  setTimeout(function(){
    console.info(c);
  }, 100)
}
洪涛

First of all, the fs module has two methods to determine whether a file exists, one is fs.exists(path, callback), which has an asynchronous callback function; the other is fs.existsSync(path), which is synchronous and returns a bool value.

Then your problem here is that fpath appears in the outer scope of the callback function, causing the fpath to always be the same.

So, there are two ways to solve this problem:
1. Use fs.existsSync(path) and use synchronization
2. Closure:

(function(fpath){
    nodeRequire('fs').exists(fpath, function (exists) {    
        dlog(fpath);//位置2
    });
}(fpath))
Peter_Zhu

is a basic closure problem. There are two solutions:
node version 0.x.x, write an immediate execution function in the loop:

for(var i = 0; i < res.length;i++){
                
               +function(i){ var info = res[i];
                var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
                
                dlog(fpath);//位置1
                
                nodeRequire('fs').exists(fpath, function (exists) {
                    
                    dlog(fpath);//位置2
                });  
                }(i);  
}  

The node version is greater than 4.x.x+, change var to let:

for(let i = 0; i < res.length;i++){
                
                var info = res[i];
                var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
                
                dlog(fpath);//位置1
                
                nodeRequire('fs').exists(fpath, function (exists) {
                    
                    dlog(fpath);//位置2
                });    
}  
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template