node学习笔记

初学记录

需要了解的知识点

  • Git Bash常用命令
  • Node.js HTTP 使用详解
  • 通读cheerio API
  • NodeJS中的EventEmitter模块
  • Promise
    • 大白话讲解Promise(一) - 需要熟悉
    • 大白话讲解Promise(二)理解Promise规范 - 了解即可
    • 大白话讲解Promise(三)搞懂jquery中的Promise - 了解即可
  • Bluebird-NodeJs的Promise
  • bluebird.js - 让所有浏览器都支持 ES6 Promise 对象
  • nodejs异步控制「co、async、Q 、『es6原生promise』、then.js、bluebird」有何优缺点?
  • node.js中的fs.createReadStream方法使用说明
  • Node.js的原型继承函数 util.inherits

有用的插件

  • 插件介绍
    • cheerio - 能在服务器端运行的 jQuery 核心实现 - 用于制作网络爬虫
    • bluebird - 封装了 ES6 原生 Promise
  • packages.json 列表(方便大家一键安装)

    {
      "devDependencies": { "bluebird": "^3.4.6", "cheerio": "^0.22.0" } }

小示例

  • http.STATUS_CODES - 服务器状态码

    var http = require('http');
    
    http.createServer(function(req,res){
        var status = req.url.substr(1);
        res.writeHeader(200, {'Content-Type':'text/plain'});
        res.end(status + http.STATUS_CODES[status]);
    }).listen(3000);
    
    console.log('开启服务器...');

    运行上面代码后,在地址栏打开 http://localhost:3000/200,将看到页面显示 200OK

  • http.createServer() - 开启一个简单的服务器

    • 方法一

      var http = require('http');
      
      http.createServer(function(request, response) {
          response.writeHead('200', {'Content-Type': 'text/plain;charset=utf-8'});
          response.end('你好,世界!');
      }).listen(3000);
      
      console.log('服务器已开启...');
    • 方法二

      var http = require('http'),
          server = new http.Server();
      
      server.on('request', function(req, res) {
          res.writeHeader(200,{'Content-Type':'text/plain;charset=utf-8'});
          res.end('你好,世界!');
      });
      
      server.listen(3000, function() {
          console.log('监听 3000');
      });
  • http.request() - 客户端模拟请求上个示例开启的服务器

    var http = require('http');
    
    var req = http.request({
        port: 3000,
    }, function(res) {
        console.log( JSON.stringify(res.headers), '---');
        res.setEncoding('utf-8');
        res.on('data', function(chunk) {
            console.log(chunk, '+++');
        });
    });
    
    req.end();// http.get() 则不需要写这句话
  • fs - 操作文件

    • 读取文件内容

      var fs = require('fs');
      var data = fs.readFile('router.js', function(err, data){
          if(err) return console.log('错了');
          console.log(data.toString());
      });
      console.log('正在读取文件...');
    • 一些操作

      var fs = require('fs');
      var buffer = new Buffer(1024);
      
      // 更改文件名
      fs.rename('test_new.js', 'test_old.js', function() {
          console.log('test_new.js更名为test_old.js');
      });
      
      // 打开文件并写入数据
      fs.open('test_old.js', 'r+', function(err, fd) {
          if(err) return console.log(err);
          var data = 'some content';
      
          fs.write(fd, buffer, 0, data.length, 0, function(err, bytes) {
              if(err) return console.log(err);
              console.log('写入了'+ bytes +'字节');
          });
      });
      
      // 创建新文件夹
      fs.mkdir('test', function(err) {
          if(err) return console.log(err);
          console.log('test文件夹创建成功');
      });
    • 复制图片

      var fs = require('fs');
      
      // 读取一张图片
      fs.readFile('../images/a.png', function(err, data) {
          if(err) return console.log(err);
          console.log(Buffer.isBuffer(data));// 是否是 Buffer 实例
      
          // 复制该图片
          fs.writeFile('../images/b.png', data, function(err) {
              if(err) return console.log(err);
              console.log('复制成功');
          });
      
          var base64Data = data.toString('base64');// 转换为 base64
      
          var buf = new Buffer(base64Data, 'base64');// 声明 base64 Buffer区
      
          // 再次复制该图片
          fs.writeFile('../images/c.png', base64Data, {
              encoding: 'base64'// 指明数据来源类型
          }, function(err) {
              if(err) return console.log(err);
              console.log('再次复制成功');
          });
      });
  • events - 触发一个事件

    • 注册和删除事件

      var EventEmitter = require('events').EventEmitter;
      
      var eventEmitter = new EventEmitter();// 生成 EventEmitter 实例
      
      eventEmitter.on('say', function(str) {// 注册 say 事件(匿名)
          console.log('say '+ str);
      });
      
      // 定义有名函数,方便下面删除此事件
      function seeSome(str) {
          console.log('see '+ str);
      }
      
      eventEmitter.on('see', seeSome);// 注册 see 事件(有名)
      
      eventEmitter.emit('say', 'apple');// 触发 say 事件
      eventEmitter.emit('see', 'banana');// 触发 see 事件
      
      eventEmitter.removeListener('see', seeSome);// 删除 see 事件(有名)
      eventEmitter.emit('see', 'banana');// 触发 see 事件
    • 继承事件模块

      var util = require('util'),
          EventEmitter = require('events').EventEmitter;
      
      // 定义一个 Cat 类
      function Cat(name) {
          this.name = name;
      }
      
      // Cat 类继承 EventEmitter
      util.inherits(Cat, EventEmitter);
      
      // 生成 Cat 的实例 Tom
      var Tom = new Cat('Tom');
      
      // 注册 say 事件
      Tom.on('say', function(str) {
          console.log(this.name, str);
      });
      
      // 触发 say 事件
      Tom.emit('say', 'miao~');
  • Buffer - 缓冲区

    // 创建一个缓冲区
    var buffer = new Buffer(30);
    console.log(buffer.length);
    
    // 写入数据
    var buf = new Buffer('hello 你好');
    
    console.log(buf.toString());
    
    buf.write('在吗');// 在 buf 长度范围内,写入的数据会覆盖之前的数据
    
    console.log(buf.toString(), buf.toString('base64'));
    
    // 截取数据
    var b = buffer.slice(1, 4);// 1<=x<4
    console.log(b.length, b.toString('ascii'));
  • Stream - 流

    • readStream和writeStream - 读取和写入

      var fs = require('fs');
      
      var readStream = fs.createReadStream('../images/a.png'),
          writeStream = fs.createWriteStream('../images/b.png');
      
      readStream.on('data', function(chunk) {
              if(!writeStream.write(chunk)) {// 防止 I/O(读取/写入) 速度不均导致磁盘被占满
                  console.log('pause');
                  readStream.pause();// 还没写完,暂停
              }
          }).on('end', function() {
              writeStream.end();
              console.log('end');
          }).on('close', function() {
              console.log('close');
          }).on('error', function(err) {
              console.log(err);
          });
      
      writeStream.on('drain', function() {
          console.log('resume');
          readStream.resume();// 写完,重新开始
      });
    • pipe() - 管道流

      var http = require('http'),
          fs = require('fs'),
          request = require('request');
      
      http.createServer(function(req, res) {
          /* 老方法
          fs.readFile('../images/a.png', function(err, data) {
              if(err) {
                  res.end(err);
              }else {
                  res.end(data);
                  console.log('end');
              }
          });*/
          //fs.createReadStream('../images/a.png').pipe(res);// 使用 pipe 的新方法
          request('https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png').pipe(res);// 使用 request模块 读取网络图片
      }).listen(3000);
      
      
      request('https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png').pipe(fs.createWriteStream('../images/b.png'));// 使用 request模块 读取网络图片,并保存
  • os - 操作系统相关

    var os = require('os');
    
    console.log(os.tmpdir());// 临时文件操作系统的默认目录
    console.log(os.hostname());// 操作系统的主机名
    console.log(os.type());// 操作系统名称
    console.log(os.platform());// 操作系统平台
    console.log(os.arch());// 操作系统的CPU架构
  • path - 文件路径相关

    var path = require('path');
    
    console.log(path.normalize('test/test.js'));// 规范化字符串路径
    console.log(path.isAbsolute('test.js'));// 路径是否是一个绝对路径
    console.log(path.dirname('test/test.js'));// 路径的目录名称
  • net - 创建服务器和客户端

    • main.js - 在一个cmd中运行,创建服务器

      var net = require('net');
      
      var server = net.createServer(function(connection) {
          connection.on('end', function() {
              console.log('断开连接');
          });
          connection.write('欢迎访问本链接');
          connection.pipe(connection);
      });
      
      server.listen(3000, function() {
          console.log('正在监听');
      });
    • app.js - 在另一个cmd中运行,创建客户端

      var net = require('net');
      
      var client = net.connect({port: 3000}, function() {
          console.log('连接到服务器');
      });
      
      client.on('data', function(data) {
          console.log(data.toString());
          client.end();
      });
      
      client.on('end', function(data) {
          console.log('断开连接');
      });
  • dns - DNS查找

    var dns = require('dns');
    
    dns.lookup('www.baidu.com', function(err, address, family) {
        if(err) return console.log(err);
        console.log('address:'+ address, 'family:'+ family);
    
        dns.reverse(address, function(hostnames) {
            if(err) return console.log(err);
            console.log(hostnames);
        });
    });
  • 爬虫实例

    var http = require('http'),
        cheerio = require('cheerio');
    
    // 获取网页标题
    function getTitle(html) {
        var $ = cheerio.load(html);// 加载 html 结构
    
        console.log($('title').text());
    }
    
    http.get('http://www.baidu.com', function(res) {
        var html = '';
        res.on('data', function(chunk) {
            html += chunk;
        });
    
        res.on('end', function() {
            getTitle(html);
        });
    });
  • Promise

    • 传递 resolve 的数据

      // 定义函数
      function runAsync(){
          // 直接返回 Promise 实例
          return new Promise(function(resolve, reject){
              //做一些异步操作
              setTimeout(function(){
                  console.log('执行完成');
                  resolve('传递数据');
              }, 1000);
          });
      }
      
      // 链式调用 runAsync
      runAsync()
      .then(function(data) {
          console.log(data);// 获取传递的数据
          return runAsync();
      })
      .then(function(data) {
          console.log(data);// 获取传递的数据
          return runAsync();
      })
    • 传递 resolve 或者 reject 的数据

      var index = 0;// 执行回调的次数
      
      // 定义函数
      function runAsync(){
          index++;
          // 直接返回 Promise 实例
          return new Promise(function(resolve, reject){
              //做一些异步操作
              setTimeout(function() {
                  var num = Math.ceil(Math.random()*10);
                  console.log('第'+ index +'次随机的数字是'+ num);
      
                  if(num%2) {// 奇数
                      resolve('第'+ index +'次随机的数字是奇数');// 成功的回调
                  }else {// 偶数
                      reject('第'+ index +'次随机的数字是偶数');// 失败的回调
                  }
                  console.log('第'+ index +'次回调完成');
              }, 100);
          });
      }
      
      // 链式调用 runAsync
      runAsync()// 第 1 次调用 runAsync
      .then(function(data) {// 第 1 次调用的 resolve 回调
          console.log(data, '奇数会输出这里');
          return runAsync();// resolve 回调同时第 2 次调用 runAsync
      }, function(data) {// 第 1 次调用的 reject 回调
          console.log(data, '偶数会输出这里');
          return runAsync();// reject 回调同时第 2 次调用 runAsync
      })
      .then(function(data) {// 第 2 次调用的 resolve 回调
          console.log(data, '奇数会输出这里');
          return runAsync();// resolve 回调同时第 3 次调用 runAsync
      }, function(data) {// 第 2 次调用的 reject 回调
          console.log(data, '偶数会输出这里');
          return runAsync();// reject 回调同时第 3 次调用 runAsync
      })
      .then(function(data) {// 第 3 次调用的 resolve 回调
          console.log(data, '奇数会输出这里');
      }, function(data) {// 第 3 次调用的 reject 回调
          console.log(data, '偶数会输出这里');
      });
    • Promise.all() - 所有异步操作执行完后才执行回调

      // 定义函数
      function runAsync(num){
          // 直接返回 Promise 实例
          return new Promise(function(resolve, reject){
              //做一些异步操作
              setTimeout(function() {
                 resolve('文章'+ num);
              }, 100);
          });
      }
      
      // 将返回的 Promise 实例添加进数组
      var runAsyncArray = [];
      for(var i=0; i<3; i++) {
          runAsyncArray.push(runAsync(i+1));
      }
      
      Promise
      .all(runAsyncArray)// 执行所有的 Promise
      .then(function(data) {
          console.log(data);// 全部完成之后,执行这里
      });

进阶记录

你可能感兴趣的:(node.js)