美文网首页我爱编程
Node.js包教不包会|实验代码+运行结果

Node.js包教不包会|实验代码+运行结果

作者: 茱小夭 | 来源:发表于2017-08-30 17:17 被阅读0次

    课程来源:https://www.shiyanlou.com/courses/493【@实验楼】

    第1节 一个最简单的 express 应用

    1.1 新建lesson1,进去里面安装express

    1.2 新建app.js

    app.js 代码

    1.3 运行app.js,打开浏览器,输入http://localhost:3000/

    浏览器结果

    第2节 学习使用外部模块

    2.1 新建lesson1,并生成一份它的 package.json。

    package.json

    2.2 安装依赖, express 和 utility 两个模块

    package.json添加了依赖信息

    2.3 新建app.js

    app.js 代码

    2.4 运行app.js,在浏览器输入http://localhost:3000/?q=alsotang

    浏览器结果

    第3节 使用 superagent 与 cheerio 完成简单爬虫

    3.1 新建文件夹,进去之后 npm init

    新建lesson3文件夹并进入 新建package.json

    3.2 安装依赖:express,superagent,cheerio

    3.3 写应用逻辑

    新建app.js app.js 代码

    3.4 运行及结果

    运行app.js 浏览器运行结果

    第4节 使用 eventproxy 控制并发

    4.1 获取主页

    4.1.1 新建文件夹,进去之后 npm init

    4.1.2 安装依赖:express,superagent,cheerio

    4.1.3 写应用逻辑

    新建 app.js app.js 代码

    4.1.4 运行及结果

    获取的链接(部分截图)

    4.2 eventproxy介绍

    4.2.1 不使用 eventproxy 也不使用计数器

    // 参考 jquery 的 $.get 的方法
    $.get("http://data1_source", function (data1) {
      // something
      $.get("http://data2_source", function (data2) {
        // something
        $.get("http://data3_source", function (data3) {
          // something
          var html = fuck(data1, data2, data3);
          render(html);
        });
      });
    });
    

    4.2.2 使用计数器

    (function () {
      var count = 0;
      var result = {};
    
      $.get('http://data1_source', function (data) {
        result.data1 = data;
        count++;
        handle();
        });
      $.get('http://data2_source', function (data) {
        result.data2 = data;
        count++;
        handle();
        });
      $.get('http://data3_source', function (data) {
        result.data3 = data;
        count++;
        handle();
        });
    
      function handle() {
        if (count === 3) {
          var html = fuck(result.data1, result.data2, result.data3);
          render(html);
        }
      }
    })();
    

    4.2.3 使用eventproxy

    var ep = new eventproxy();
    ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) {
      var html = fuck(data1, data2, data3);
      render(html);
    });
    
    $.get('http://data1_source', function (data) {
      ep.emit('data1_event', data);
      });
    
    $.get('http://data2_source', function (data) {
      ep.emit('data2_event', data);
      });
    
    $.get('http://data3_source', function (data) {
      ep.emit('data3_event', data);
      });
    

    eventproxy 提供了不少其他场景所需的 API,但最最常用的用法就是以上的这种,即:

    • 先 var ep = new eventproxy(); 得到一个 eventproxy 实例。
    • 告诉它你要监听哪些事件,并给它一个回调函数。
      ep.all('event1', 'event2', function (result1, result2) {})。
    • 在适当的时候 ep.emit('event_name', eventData)。

    4.3 抓取每条url的内容

    完整代码如下:

    var eventproxy = require('eventproxy');
    var superagent = require('superagent');
    var cheerio = require('cheerio');
    var url = require('url');
    
    var cnodeUrl = 'https://cnodejs.org/';
    
    superagent.get(cnodeUrl)
      .end(function (err, res) {
        if (err) {
          return console.error(err);
        }
        var topicUrls = [];
        var $ = cheerio.load(res.text);
        $('#topic_list .topic_title').each(function (idx, element) {
          var $element = $(element);
          var href = url.resolve(cnodeUrl, $element.attr('href'));
          topicUrls.push(href);
        });
    
        var ep = new eventproxy();
    
        ep.after('topic_html', topicUrls.length, function (topics) {
          topics = topics.map(function (topicPair) {
            var topicUrl = topicPair[0];
            var topicHtml = topicPair[1];
            var $ = cheerio.load(topicHtml);
            return ({
              title: $('.topic_full_title').text().trim(),
              href: topicUrl,
              comment1: $('.reply_content').eq(0).text().trim(),
            });
          });
    
          console.log('final:');
          console.log(topics);
        });
    
        topicUrls.forEach(function (topicUrl) {
          superagent.get(topicUrl)
            .end(function (err, res) {
              console.log('fetch ' + topicUrl + ' successful');
              ep.emit('topic_html', [topicUrl, res.text]);
            });
        });
      });
    
    运行结果(部分截图)

    第5节 使用 async 控制并发

    5.1 准备工作

    • mkdir lesson5 && cd lesson5
    • npm init
    • npm install --save async
    • touch app.js

    5.2 app.js 代码如下

    5.3 运行及结果

    结果 部分截图1 结果 部分截图2

    第6节 测试用例:mocha,should,istanbul

    6.1 编写测试用例

    6.1.1 准备工作

    6.1.2 编写测试用例

    新建 main.js main.js 代码

    6.1.3 运行及结果

    符合预期

    6.2 执行测试

    6.2.1 修改main.js,暴露 fibonacci

    在末尾加这句

    6.2.2 准备工作

    安装依赖:should 新建test文件夹及test.main.js

    6.2.3 main.test.js 代码

    安装mocha

    6.2.4 运行及结果

    安装 mocha 在lesson6目录下运行测试文件 运行结果:测试通过

    6.2.4 增加测试,修改main.test.js,并运行

    main.test.js 运行结果:有3个没通过

    6.2.5 根据报错更新main.js,使测试全部通过

    更新fibonacci 运行结果:全部通过

    以上过程为TDD(测试驱动开发):先把要达到的目的都描述清楚,然后让现有的程序跑不过 case,再修补程序,让 case 通过。

    6.3 使用isbantul(代码覆盖率)

    • 行覆盖率(line coverage):是否每一行都执行了?
    • 函数覆盖率(function coverage):是否每个函数都调用了?
    • 分支覆盖率(branch coverage):是否每个if代码块都执行了?
    • 语句覆盖率(statement coverage):是否每个语句都执行了?

    6.3.1 准备工作

    • subo npm install --global mocha
    • sudo npm install --save-dev mocha
    • sudo nom i istanbul -g
    • istanbul cover _mocha

    6.3.2 运行结果


    第7节 浏览器端测试:mocha,chai,phantomjs

    7.1 浏览器环境执行

    7.1.1 准备工作

    • mkdir lesson7 && cd lesson7
    • mkdir vendor && cd vendor
    • npm i -g mocha # 安装全局的 mocha 命令行工具
    • mocha init . # 生成脚手架
    测试原型目录结构

    7.1.2 在index.html插入如下代码

    7.1.3 在test.js输入如下代码

    7.1.4 打开index.html,结果如下

    7.2 命令行环境执行

    7.2.1 安装 mocha-phantomjs

    • sudo npm i -g mocha-phantomjs

    7.2.2 index.html增加如下代码

    7.2.3 运行

    报错,不知道是什么原因??


    第8节 测试用例:supertest

    8.1 准备工作

    8.2 编写app.js

    8.3 编写test/app.test.js

    8.4 运行及结果

    --

    第9节 正则表达式

    • i :不区分大小写
    • g:匹配多个
    • m :^ 和 $ 可以匹配每一行的开头。
    • 加 g 会返回数组,不加 g 则返回比较详细的信息
    • 加 g 之后,如果你的正则不是字面量的正则,而是存储在变量中的话,这个变量就会变得有记忆
    • [\s\S],[^]:能匹配包括 \n 在内的所有字符

    第10节 benchmark 怎么写(测试性能)

    • mkdir lesson10 && cd lesson10
    • npm init
    • npm install benchmark --save
    • touch main.js

    第11节 作用域与闭包

    11.1 var作用域

    • 内部函数可以访问外部函数的变量,外部不能访问内部函数的变量。
    ex1.js 运行及结果

    内部函数child可以访问变量age,而外部函数parent不可以访问child中的变量childAge,因此会抛出没有定义变量的异常。

    • 如果忘记var,那么变量就被声明为全局变量了。
    ex2.js 运行及结果
    • JavaScript 中,变量的局部作用域是函数级别的。不同于 C 语言,在 C 语言中,作用域是块级别的。
    ex3.js 运行及结果

    11.2 闭包

    ex4.js 运行及结果
    • 闭包的一个坑
    ex5.js 运行及结果
    • 上面这个代码块打印五个 5:setTimeout 中的 i 是对外层 i 的引用。当 setTimeout 的代码被解释的时候,运行时只是记录了 i 的引用,而不是值。而当 setTimeout 被触发时,五个 setTimeout 中的 i 同时被取值,由于它们都指向了外层的同一个 i,而那个 i 的值在迭代完成时为 5,所以打印了五次 5。
    • 下面这个代码块打印0-4:把 i 赋值成一个局部的变量,从而摆脱外层迭代的影响。

    11.3 this

    • 函数有所属对象时:指向所属对象
    ex6.js 运行及结果
    • 函数没有所属对象:指向全局对象
    ex7.js 运行及结果 运行及结果(接上)
    • 构造器中的 this:指向新对象
    ex8.js 运行及结果
    • apply 和 call 调用以及 bind 绑定:指向绑定的对象
    ex9.js 运行及结果 运行及结果(接上)

    第13节 持续集成平台:travis

    13.1 注册travis账号

    https://travis-ci.org/

    我直接关联了自己的github账号

    13.2 选择自己需要测试的仓库

    仓库主目录结构 test目录结构

    13.3 写.travis.yml

    13.4 运行及结果

    当 .travis.yml 完成后,travis自动被触发

    点击查看结果 详细结果

    15.2 使用mongodb和mongoose模块

    • mkdir lesson15 && cd lesson15
    • touch test_db.js
    • npm install mongoose
    test_db.js 代码
    • node test_db.js
    添加成功
    • mongod
    • 在另一个终端输入 mongo
    数据库结果

    相关文章

      网友评论

        本文标题:Node.js包教不包会|实验代码+运行结果

        本文链接:https://www.haomeiwen.com/subject/knxidxtx.html