关闭

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

标签: nodejsjs
444人阅读 评论(0) 收藏 举报
分类:

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
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

nodejs v8中的回调机制

本文地址 http://blog.csdn.net/wangjia184/article/details/18940165 如果要在nodejs中调用动态链接库中的导出方法,或者从动态链接库...
  • zs10hz
  • zs10hz
  • 2014-11-03 16:31
  • 1429

nodejs回调大坑

最近看到nodejs,因为有一个处理里面有好几个异步操作,调入回调大坑,不禁觉得很恶心,真的很讨厌发明这种写法的人,简直反社会!!!遂转载一篇解坑的文章,原文地址:http://www.infoq.c...
  • neal1991
  • neal1991
  • 2016-04-27 08:57
  • 3356

在Node.js中使用promise摆脱回调金字塔

http://nya.io/Node-js/promise-in-nodejs-get-rid-of-callback-hell/ 在开始谈论正题之前,我们先来看看下面一段代码: ...
  • SalmonellaVaccine
  • SalmonellaVaccine
  • 2015-08-12 13:27
  • 869

Nodejs中“循环+异步” 好深的坑!!

这几天在搞Nodejs从数据库中获取数据进行格式转换,折腾了好几个日日夜夜,各种循环+异步操作,最后发现这玩意好恶心,怎么每次运行结果都会变,有时报错哪个值undefined有时正常,简直吐血,经历无...
  • u011249920
  • u011249920
  • 2017-01-11 08:10
  • 5429

如何更优雅的书写Javascript之告别回调地狱

什么是回调地狱? PS: 某大牛说过,世上本没有多层回调嵌套,写的人多了也便有了。 下面我们举个例子 在使用jquery animat做多个动画效果的时候,可能很多的童鞋写出过如下的...
  • vuturn
  • vuturn
  • 2015-04-13 13:42
  • 4257

关于nodejs中的回调函数理解

Node的三个特点:单线程,非阻塞I/O,事件驱动。Node的编程思维就是,所有的都是异步的,因此有了大量的回调函数。 回调函数,就是放在另外一个函数(如 parent)的参数列表中,作为参数传递给这...
  • mimikuer
  • mimikuer
  • 2017-12-22 11:14
  • 52

nodejs单线程、异步事件的理解

都说nodejs是单线程,异步非阻塞了,不了解的人总会犯迷糊——它既是单线程的,如何又是异步的呢? 这里需要知道的是,通常我们所写的代码都是在单线程中执行的,但是nodejs自身却不是单线程的。 ...
  • baidu20008
  • baidu20008
  • 2014-09-25 15:51
  • 2063

函数回调机制、异步函数回调机制图例详解

无论是JS的函数回调还是Java回调机制,它们思想都是类似的,简单来说就是,如下图所示:                             &#...
  • zhangliangzi
  • zhangliangzi
  • 2016-07-29 20:10
  • 6311

javascript异步代码的回调地狱以及JQuery.deferred提供的promise解决方案

由于AJAX是异步的,所有依赖AJAX返回结果的代码必需写在AJAX回调函数中。这就不可避免地形成了嵌套,ajax等异步操作越多,嵌套层次就会越深,代码可读性就会越差。Promise对象有3种可能的状...
  • aitangyong
  • aitangyong
  • 2015-07-22 17:23
  • 3786

异步调用和回调函数

异步调用在应用程序框架中具有广泛的应用,并且特指多线程情况下。它同Windows的消息循环机制,消息响应,消息队列,事件驱动机制以及设计模式中的观察者模式等都是紧密相关的。        回调函数用于...
  • kobejayandy
  • kobejayandy
  • 2013-12-29 16:26
  • 9461
    个人资料
    • 访问:21061次
    • 积分:246
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:0篇
    • 译文:0篇
    • 评论:15条
    文章分类
    文章存档
    最新评论