nodejs中异步回调总有些不完美

nodejs借助于node运行环境而实现的一个比较灵巧的前后一体化的开发环境,随比不了php,python,但是在快速开发维护的时间成本上,node一骑绝尘。node自身由衷的想法,花最小的硬件成本,追求更高的并发,更高的处理性能。

nodejs是一个让javascript运行在服务端的开发平台,它让javascript的触角伸到了服务器,可以与php,jsp,python,ruby平起平坐


node的与众不同之处:

1.node.js不是一门独立的语言,与php,jsp,python, perl,ruby的"既是语言,也是平台"不同,node.js的使用javascript进行编程,运行在chrom的v8引擎之上。它自己不用建设在任何的服务器软件之上。


node特点:

1.单线程

2.非阻塞

3.事件驱动

首先,node不为每一个用户开辟一个线程,所以非常极端的选择了单线程。单线程,要照顾好所有的用户,那么就必须有非阻塞I/O,否则一个人的I/O就把别人,自己的都给阻塞了。一旦有了非阻塞的I/O,一个人如果I/O去了,就会放弃CPU的使用权,换成另一个人使用CPU(或者执行此人后面的语句)。所以CPU的利用率100%。第一个人I/O结束了,就要用事件来通知线程,执行回调函数。此时必须有事件环,就有一个人排队调度机制。Node中有超过半数的C++代码,在搭建事件环


nodejs适合做:

大量的/并发的、网络,文件 I/O

例如,表单提交、考试系统,聊天室,图文直播


不适合做:

由于nodejs善于io不善于计算,复杂的业务逻辑运算



nodejs中回调是优美的实现,这句话没错,但总有些时候我们不想因为异步回调而产生一些不必要的麻烦

存在的问题:

/**
 * 需求是遍历某文件夹,只遍历一级(文件或文件夹)中的文件夹,并打印到控制台
 */
let fs = require("fs");
let http = require("http");

// 1.模拟本地服务器
let server = http.createServer(function(req, res){
    // 2.规避调由chrome浏览器收藏夹发起的访问的请求
    if(req.url == '/favicon.ico'){
        return;
    }
    
    // 3.读取一个文件夹
    fs.readdir('./album', function(err, files){
        // 4.声明一个空数组来存放所有的子文件夹
        let folderArray = [];


        // 此处的就是因为nodejs的回调'太过于无处不在'导致会出现局部变量污染的问题,
        // 分析如下: 
        // 假设files[0]='folder1',
        // 试着想一下由于是异步回调,当第一个for循环走完,获取if中的判断还没有执行到,
        // 紧接着for走到第二次循环此时files[2]='a.txt',此时if判断恰巧执行到,
        // 试问此时的folderArray.push(files[i]);就不是'folder1',而是'a.txt'
        // 于是问题就出现了!
        for(var i = 0; i < files.length; i ++){
            fs.stat('./album/' + files[i], function(err, stats){
                if(stats.isDirectory()){
                    folderArray.push(files[i]);
                }
                console.log(folderArray);
            });
        }
        console.log(folderArray);
    });
    
    res.end();

}).listen(3000, '127.0.0.1');



纠正方案

/**
 * 需求是遍历某文件夹,只遍历一级(文件或文件夹)中的文件夹,并打印到控制台
 */
let fs = require("fs");
let http = require("http");

// 1.模拟本地服务器
let server = http.createServer(function(req, res){
    // 2.规避调由chrome浏览器收藏夹发起的访问的请求
    if(req.url == '/favicon.ico'){
        return;
    }
    
    // 3.读取一个文件夹
    fs.readdir('./album', function(err, files){
        // 4.声明一个空数组来存放所有的子文件夹
        let folderArray = [];

        /**
         * 牛x的地方在这里出现,强行将同步变成异步
         *    -- 自己定义一个函数并且使之立即执行(function method(args){...})(args)
         */
        (function iterator(i){
            // 5.控制数组下标不越界
            if(i == files.length){
	        // 6.输出满足条件的文件夹
	        console.log(folderArray);
                return;
            }
            // 7.对files中的元素开始逐一遍历
            fs.stat('./album/' + files[i], function(err, stats){
                // 8.如果是文件夹则就放入上面预定义的数组内
                if(stats.isDirectory()){
                    folderArray.push(files[i]);
                }
                // 9. 此处是关键点,也正是这里才是强制同步遍历
                iterator(i + 1);
            });
        })(0);

    });
    res.end();

}).listen(3000, '127.0.0.1');




这种问题在读数据库时一定要格外注意!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值