찾다

 >  Q&A  >  본문

node.js - nodejs异步编程变量传递的问题。

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中文网2784일 전618

모든 응답(3)나는 대답할 것이다

  • PHPz

    PHPz2017-04-17 14:31:24

    原因

    你没有问原因不过我还是说一下原因吧。

    fpath变量只是一个变量(引用),而你传递的回调函数只知道:“哦,到时我可以去获得(引用)fpath的值”。

    关键在于你传递函数时,传递的只是一个未执行的函数,函数里有fpath这一个变量,由于未执行,并未获得当前值。

    等异步函数要去获取的时候,fpath的值已经是最后一个了。

    解法

    假设问题为:

    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)
    }

    解法一:(原始解法)
    解法也很简单,上面说了当时的函数没有执行,我们可以创建一个函数执行一部分,用另外一个(新的函数的)变量存起来。

    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)
    }

    解法二:(es6解法)

    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)
    }

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-17 14:31:24

    首先,fs模块,判断文件是否存在有两个方法,一个是fs.exists(path, callback),有一个异步回调函数;还有一个是fs.existsSync(path),这个方法是同步的,返回一个bool值。

    然后是你这里的问题,是由于fpath出现在了回调函数的外部作用域中,造成了fpath总是同一个。

    所以,有两个方法解决这个问题:
    1.使用fs.existsSync(path),使用同步的方式
    2.闭包:

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

    회신하다
    0
  • 天蓬老师

    天蓬老师2017-04-17 14:31:24

    就是一个基础的闭包问题, 解法有二:
    node版本0.x.x,在循环中写立即执行函数:

    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);  
    }  

    node版本大于4.x.x+,把var 改为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
                    });    
    }  

    회신하다
    0
  • 취소회신하다