zoukankan      html  css  js  c++  java
  • Node异步污染局部变量问题

    看一个例子:

    这么一个文件夹:

    现在我们用fs模块判断文件夹,并把文件夹的名字放在一个数组里面。

    代码:

    var http = require("http");
    
    var fs = require("fs");
    
    http.createServer(function(req, res) {
        if(req.url == "favicon") {
            return ;
        }
        var ddir = [];
        //stat检测状态
        fs.readdir("./album", function(err, files) {
            //files是一个文件名的数组,并不是文件的数组,表示./album这个文件夹中的所有集合
            //包括文件,文件夹
            for(var i = 0; i < files.length; i++) {
                var thefilename = files[i];
                // 又要进行一次检测
                fs.stat("./album/" + thefilename, function(err,stats) {
                    //如果他是一个文件夹,那么输出它:
                    if(err) {
                        throw err;
                    }
                    if(stats.isDirectory()) {
                        ddir.push(thefilename);
                    }
                    console.log(ddir);
                });
                // console.log(thefilename);
            }
        })
    }).listen(3000,"127.0.0.1");

    这样按照同步的思想是没错的,但是Node是异步执行的,结果:

    呀!结果和我们臆想的有点不一样吧。这就是Node在检测stats是不是文件夹的时候,由于是异步语句,还没有检查完,就已经开始执行下一次了,下一次的时候thefilename变成了bbb,这时候第一个事件的检查文件的异步语句完成了,push进ddir数组,push的thefilename是bbb,第二个事件也只有bbb了,所以最后输出的是良哥bbb。前面三个空是三个异步语句注册的三个事件进入队列,这时候同步执行的下面的console.log(ddir);都还是空数组。

    那么问题就来了,怎么解决呢?

    闭包解决,递归

    var http = require("http");
    var fs = require("fs");
    
    var server = http.createServer(function(req, res) {
        //不处理收藏夹小图标
        if(req.url == "favicon.ico") {
            return ;
        }
        //遍历album里面的所有文件,文件夹
        fs.readdir("./album/", function(err, files) {
            //files是一个存放文件(夹)名的数组
            //files: ["aaa","bbb","1.txt","1.txt副本"]
            //存放文件夹的数组wenjianjia
            var wenjianjia = [];
            //迭代器就是强行把异步的函数,变成同步的函数
            //0做完了,做1,1做完了,再做2,再做3
            (function iterator(i) {
                //遍历结束
                if(i == files.length) {
                    console.log(wenjianjia);
                    return ;
                }
                fs.stat("./album/" + files[i], function(err, stats) {
                    //检测成功之后做的事情
                    if(stats.isDirectory()) {
                          //如果是文件夹,那么放入数组。不是,什么也不做
                          wenjianjia.push(files[i]);
                    }
                    //递归
                    iterator(i+1);
                });
            })(0);
        });
        res.end();
    })
    
    server.listen(3000,"127.0.0.1");

    重构一下:

    var http = require("http");
    var fs = require("fs");
    
    
    var wenjianjia = [];
    function iterator(i,files) {
        //遍历结束
        if (i == files.length) {
            console.log(wenjianjia);
            return;
        }
        fs.stat("./album/" + files[i], function(err, stats) {
            //检测成功之后做的事情
            if (stats.isDirectory()) {
                //如果是文件夹,那么放入数组。不是,什么也不做。
                wenjianjia.push(files[i]);
            }
            iterator(i + 1, files);
        });
    }
    
    var server = http.createServer(function(req, res) {
        //不处理收藏夹小图标
        if (req.url == "/favicon.ico") {
            return;
        }
        //遍历album里面的所有文件、文件夹
        fs.readdir("./album/", function(err, files) {
            //files : ["0.jpg","1.jpg" ……,"aaa","bbb"];
            //files是一个存放文件(夹)名的数组
            //存放文件夹的数组
            //album读完了,执行回调函数,此时才有files,同步-》异步-》回调
            //迭代器就是强行把异步的函数,变成同步的函数
            //1做完了,再做2;2做完了,再做3
            iterator(0,files);
        });
    
        res.end();
    });
    
    server.listen(3000, "127.0.0.1");
  • 相关阅读:
    LeetCode 剑指offer 面试题05. 替换空格
    WebSocket整合SSM(Spring,Struts2,Maven)
    Eclipse常用20个快捷键
    JDK、JRE、JVM三者间的联系与区别
    Java集合框架详解(全)
    Java开发环境配置(Jdk、Tomcat、eclipse)
    Java面向对象概述及三大特征(封装,继承和多态)
    程序员之歌
    UML2.0最新版入门图解
    java单元测试,ssh(spring,struts2,hibernate)框架整合junit4
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7741083.html
Copyright © 2011-2022 走看看