• nodejs学习(imooc课程笔记, 主讲人Scott)


    课程地址:

    进击Node.js基础(一)

    进击Node.js基础(二)

    1. nodejs创建服务器

    var http = require('http');        //加载http模块
    
    //请求进来时, 告诉服务器做什么, 于是给createServer传递一个匿名回调函数. 
    //两个参数, 前面是请求体, 后面是响应体. 请求体用来获取请求相应信息,比如请求ip地址,请求的类型get/post,res用来返回响应
    http.createServer(function(req, res) {
        res.writeHead(200, {'Content-Type': 'text/palin'});
        res.end('Hello World
    ');
    }).listen(1337, '127.0.0.1');        //通过listen使服务器在1337端口监听请求
    console.log('Server running at https://127.0.0.1:1337/');

    2. nodejs安装:

    一开始直接使用sudo apt-get install node后, 安装好的node不能启动且node -v也没有输出. node.js的版本号是v0.10.25.但是用npm安装一些包时候却说node版本不够, 没搞明白node和nodejs区别在哪里.

    于是卸载掉从nodejs.org上下了新版, 是node v6.10.0. 解压后, 直接在那个目录下可以启动node, 在网上查了使用了一个链接, 分别把node 和 npm设置了全局:

    sudo ln -s /media/hao/3b6b3418-c087-4836-a75d-6d7a6023e495/Programs/node-v6.10.0-linux-x64/bin/node /usr/sbin/node
    sudo ln -s /media/hao/3b6b3418-c087-4836-a75d-6d7a6023e495/Programs/node-v6.10.0-linux-x64/bin/npm /usr/sbin/npm

    可以用了.

    关于nodejs和node版本的区别,参考这个帖子吧: nodejs各版本的区别

    3. 模块: 从这里开始都是慕课网老师Scott进击NodeJS基础(一)(二)课程的笔记

    • 创建模块
      teacher.js
    • 导出模块
      exports.add = function(){ }
    • 加载模块
      var teacher = require('./teacher.js')
    • 使用模块
      teacher.add('Scott')

      

    4. nodejs中一些api

    1. url:
      1. url.parse
      2. url.format:
      3. url.resolve

    2. querystring

      

    5. 用nodejs做的一个爬虫:

    var http = require('http')
    var cheerio = require('cheerio')        //npm install cheerio
    var url = 'http://www.imooc.com/learn/348'
    
    function filterChapters(html){
        var $ = cheerio.load(html)
        var chapters = $('.chapter')
        // [{
        //     chapterTitle: '',
        //     videos: [
        //         title:'',
        //         id: ''
        //     ]
        // }]
        var courseData = []
        chapters.each(function(item){
            var chapter = $(this)
            var chapterTitle = chapter.find('strong').text().trim('
    ').split('
    ')[0]
            var videos = chapter.find('.video').children('li')
            var chapterData = {
                chapterTitle: chapterTitle,
                videos: []
            }
            videos.each(function(item){
                var video = $(this).find(".J-media-item")
                var videoTitle = video.text().split(/s+/).slice(1,-2).join(' ')
                var id = video.attr('href').split('video/')[1]
                chapterData.videos.push({
                    title: videoTitle,
                    id: id
                })
            })
            courseData.push(chapterData)
        })
        return courseData
    }
    
    function printCourseInfo(courseData){
        courseData.forEach(function(item){
            var chapterTitle = item.chapterTitle
            console.log(chapterTitle + '
    ')
    
            item.videos.forEach(function(video){
                console.log('   [' + video.id + ']' + video.title + '
    ')
            })
        })
    }
    http.get(url, function(res) {
        var html = ''
    
        res.on('data', function(data){
            html += data
        })
    
        res.on('end', function(){
            var courseData = filterChapters(html)
            printCourseInfo(courseData)
        })
    }).on('error', function(){
        console.log('获取课程数据错误')
    })

    6. 事件监听的一个小例子 

    var EventEmitter = require('events').EventEmitter
    var life = new EventEmitter()
    
    //addEventListener
    
    life.setMaxListeners(6)     //设置事件最大监听数 默认为10. 超出这个数目会报警告
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' 倒水')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...1')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...2')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...3')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...4')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...5')
    })
    
    life.on('求安慰', function(who){
        console.log('给 ' + who + ' ...6')
    })
    
    
    var hasBeenListener = life.emit('求安慰', '杠子')      //会返回值, 看是否被监听过
    
    //要移除函数, 不能够使用匿名函数, 只能移除具名函数
    
    console.log(life.listeners('求安慰').length)   //查询监听事件数
    console.log(EventEmitter.listenerCount(life, '求安慰'))
    
    life.removeAllListeners('求安慰')
    life.emit('求安慰','gangzi')

     7. Promise.js  imooc

    <!DOCTYPE html>
    <html>
    <head>
        <title>Promise animation</title>
        <style type="text/css">
            .ball{
                width: 40px;
                height: 40px;
                border-radius: 20px;
            }
            .ball1 { background: red;}
            .ball2 { background: yellow;}
            .ball3 { background: green;}
        </style>
        <script type="text/javascript" src="/home/hao/node_modules/bluebird/js/browser/bluebird.js"></script>
    </head>
    
    <body>
        <div class="ball ball1" style="margin-left: 0;"></div>
        <div class="ball ball2" style="margin-left: 0;"></div>
        <div class="ball ball3" style="margin-left: 0;"></div>
        
    
    </body>
    <script type="text/javascript">
        var ball1 = document.querySelector('.ball1')
        var ball2 = document.querySelector('.ball2')
        var ball3 = document.querySelector('.ball3')
        
        function animate(ball, distance, cb){
            setTimeout(function(){
                var marginLeft = parseInt(ball.style.marginLeft, 10)
                if(marginLeft === distance){
                    cb && cb()
                }
                else {
                    if(marginLeft < distance){
                        marginLeft++
                    } else {
                        marginLeft--
                    }
                    ball.style.marginLeft = marginLeft + 'px'
                    animate(ball,distance,cb)
                }
            },13);
        }
        // animate(ball1, 100, function(){
        //     animate(ball2, 200, function() {
        //         animate(ball3, 300, function(){
        //             animate(ball3, 150, function(){
        //                 animate(ball2, 150, function(){
        //                     animate(ball1, 150, function(){
    
        //                     })
        //                 })
        //             })
        //         })
        //     })
        // })
        var Promise = window.Promise
        function promiseAnimate(ball, distance){
            return new Promise(function(resolve, reject){
                function _animate(){
                    setTimeout(function(){
                        var marginLeft = parseInt(ball.style.marginLeft, 10)
                        if(marginLeft === distance){
                            resolve()
                        }
                        else {
                            if(marginLeft < distance){
                                marginLeft++
                            } else {
                                marginLeft--
                            }
                            ball.style.marginLeft = marginLeft + 'px'
                            _animate()
                        }
                    },13);
                }
                _animate()
            })
    
        }
        promiseAnimate(ball1, 100)
            .then(function() {
                return promiseAnimate(ball2,200)
            }).then(function(){
                return promiseAnimate(ball3,300)
            }).then(function(){
                return promiseAnimate(ball3,150)
            }).then(function(){
                return promiseAnimate(ball2,150)
            }).then(function(){
                return promiseAnimate(ball1,150)
            })
    </script>
    </html>
    •  Promise就是对象,有三种状态: 未完成(pending), 已完成(fulfilled), 失败(rejected). 过程不可逆
    • Promise A与A+不同点
      • A+规范通过术语thenable来区分promise对象
      • A+定义onFulfilled/onRejected必须是作为函数来调用, 而且调用过程必须是异步的
      • A+严格定义了then方法链式调用时onFulfilled/onRejected的调用顺序 

    • 使用promise改进之前的爬虫代码:
      var http = require('http')
      var Promise = require('bluebird')
      var cheerio = require('cheerio')        //npm install cheerio
      var baseUrl = 'http://www.imooc.com/learn/'
      var url = 'http://www.imooc.com/learn/348'
      var videoIds = [728,637,197,348,259,75,134]
      
      function filterChapters(html){
          var $ = cheerio.load(html)
          var chapters = $('.chapter')
          var title = $('h2.l').text()
          var number = $($('span.meta-value.js-learn-num')).text()
      
          // courseData = {
          //     title: title,
          //     number: number,
          //     videos: [{
          //         chapterTitle: '',
          //         videos: [
          //             title: '',
          //             id: ''
          //         ]
          //     }]
          // }
          var courseData = {
              title: title,
              videos: [],
              number:number
          }
          chapters.each(function(item){
              var chapter = $(this)
              var chapterTitle = chapter.find('strong').text().trim('
      ').split('
      ')[0]
              var videos = chapter.find('.video').children('li')
              var chapterData = {
                  chapterTitle: chapterTitle,
                  videos: []
              }
              videos.each(function(item){
                  var video = $(this).find(".J-media-item")
                  var videoTitle = video.text().split(/s+/).slice(1,-2).join(' ')
                  var id = video.attr('href').split('video/')[1]
                  chapterData.videos.push({
                      title: videoTitle,
                      id: id
                  })
      
              })
              courseData.videos.push(chapterData)
          })
          return courseData
      }
      
      function printCourseInfo(coursesData){
          coursesData.forEach(function(courseData){
              // console.log(courseData.number + ' 人学过' + courseData.title + '
      ')
              console.log('### ' + courseData.title + '
      ')
              courseData.videos.forEach(function(item){       
                  console.log(item.chapterTitle);
                  item.videos.forEach(function(video){
                      console.log('   [' + video.id + ']' + video.title + '
      ')
                  })
                  
              })
          })
          // coursesData.forEach(function(item){
              
                  
          // })
      }
      function getPageAsync(url){
          return new Promise(function(resolve,reject){
              console.log('正在爬取 ' + url)
              http.get(url, function(res) {
                  var html = ''
      
                  res.on('data', function(data){
                      html += data
                  })
      
                  res.on('end', function(){
                      resolve(html)
                      // var courseData = filterChapters(html)
                      // printCourseInfo(courseData)
                  })
              }).on('error', function(e){
                  reject(e)
                  console.log('获取课程数据错误')
              })
          })
      
      }
      
      var fetchCourseArray = []
      
      videoIds.forEach(function(id){
          fetchCourseArray.push(getPageAsync(baseUrl + id))
      })
      
      Promise
       .all(fetchCourseArray)
       .then(function(pages){
          var coursesData = []
          pages.forEach(function(html){
              var courses = filterChapters(html)
              coursesData.push(courses)
          })
      
          coursesData.sort(function(a,b){
              return a.number < b.number
          })
          printCourseInfo(coursesData)
       })

      

    8. Buffer API

    使用Buffer来读写图片的一个例子:

     1 var fs = require('fs')
     2 
     3 fs.readFile('logo.png', function(err, origin_buffer){
     4     console.log(Buffer.isBuffer(origin_buffer))
     5     fs.writeFile('logo_buffer.png', origin_buffer, function(err){
     6         if(err) console.log(err)
     7     })
     8 
     9     // var base64Image = new Buffer(origin_buffer).toString('base64')
    10     var base64Image = origin_buffer.toString('base64')
    11 
    12     console.log(base64Image)
    13 
    14     var decodedImage = new Buffer(base64Image, 'base64')
    15 
    16     console.log(Buffer.compare(origin_buffer, decodedImage))
    17 
    18     fs.writeFile('logo_decodes.png', decodedImage, function(err){
    19         if(err) console.log(err)
    20     })
    21 })

    9. Stream API

    //拷贝文件
    var fs = require('fs')
    var source = fs.readFileSync('../buffer/logo.png')
    
    fs.writeFileSync('stream_copy_logo.png', source)
    //拷贝图片
    var fs = require('fs')
    
    var readStream = fs.createReadStream('stream_copy_logo.js')
    var n = 0
    
    readStream
        .on('data', function(chunk) {
            n++
            console.log('data emits')
            console.log(Buffer.isBuffer(chunk))     //true  
            // console.log(chunk.toString('utf8'))     //要读的文件的内容
    
            readStream.pause()
            console.log('data pause')
            setTimeout(function(){
                console.log('data pause end')
                readStream.resume()
            }, 3000)
        })
        .on('readable', function(){
            console.log('data readable')
        })
        .on('end', function() {
            console.log(n)
            console.log('data ends')
        })
        .on('close', function() {
            console.log('data close')
        })
        .on('error', function(e){
            console.log('data read error' + e)
        })
    //拷贝视频
    var fs = require('fs')
    
    var readStream = fs.createReadStream('1.mp4')
    var writeStream = fs.createWriteStream('1-stream.mp4')
    
    readStream.on('data', function(chunk){
        //如果缓存区数据还在写, 那么暂停读数据
        if( writeStream.write(chunk) === false){
            console.log('still cached')
            readStream.pause()
        }
    })
    
    readStream.on('end', function(){
        writeStream.end()
    })
    
    writeStream.on('drain', function() {
        console.log('data drains')
    
        readStream.resume() 
    })

    10. 流与pipe

    网络请求与pipe:

     1 var http = require('http')
     2 var fs = require('fs')
     3 var request = require('request')
     4 
     5 http
     6     .createServer(function(req, res) {
     7         //=====================常规做法
     8         // fs.readFile('./buffer/logo.png', function(err, data){
     9         //     if(err){
    10         //         res.end('file not exist!')
    11         //     } else {
    12         //         res.writeHeader(200, {'Context-Type' : 'text/html'})
    13         //         res.end(data)
    14         //     }
    15         // })
    16 
    17         //===============使用pipe方法读取本地图片
    18         // fs.createReadStream('../buffer/logo.png').pipe(res)
    19 
    20         //从网络上获取一张图片 在不保存的前提下再返回给浏览器
    21         request('http://www.imooc.com/static/img/index/logo.png?t=1.1').pipe(res)
    22         //pipe会自动监听data和end事件. 可自动控制流量压力
    23     })
    24     .listen(8090)

    使用pipe重构上面的copy视频的代码:

    1 var fs = require('fs')
    2 fs.createReadStream('1.mp4').pipe(fs.createWriteStream('1-pipe.mp4'))

    总结:

    1. 可读流是为了读取外部数据, 并把数据缓存到内部的buffer数组
    2. 可写流是为了消费数据, 从可读流里获取数据然后对得到的chunk数据库进行处理.
       1 var Readable = require('stream').Readable
       2 var Writable = require('stream').Writable
       3 
       4 var readStream = new Readable()
       5 var writeStream = new Writable()
       6 
       7 readStream.push('I ')
       8 readStream.push('Love ')
       9 readStream.push('Imooc
       ')
      10 readStream.push(null)
      11 
      12 writeStream._write = function(chunk, encode, cb) {
      13     console.log(chunk.toString())
      14     cb()
      15 }
      16 
      17 readStream.pipe(writeStream)

      

    一个自己定制的读写转换流的实现:

     1 var stream = require('stream')
     2 var util = require('util')
     3 
     4 function ReadStream(){
     5     stream.Readable.call(this)
     6 
     7 }
     8 
     9 util.inherits(ReadStream, stream.Readable)
    10 
    11 ReadStream.prototype._read = function(){
    12     this.push('I ')
    13     this.push('Love ')
    14     this.push('Imooc
     ')
    15     this.push(null)
    16 }
    17 
    18 function WriteStream(){
    19     stream.Writable.call(this)
    20     this._cached = new Buffer('')
    21 }
    22 
    23 util.inherits(WriteStream, stream.Writable)
    24 
    25 WriteStream.prototype._write = function(chunk, encode, cb){
    26     console.log(chunk.toString())
    27     cb()
    28 }
    29 
    30 function TransformStream(){
    31     stream.Transform.call(this)
    32 }
    33 
    34 util.inherits(TransformStream, stream.Transform)
    35 
    36 TransformStream.prototype._transform = function(chunk, encode, cb){
    37     this.push(chunk)
    38     cb()
    39 }
    40 
    41 TransformStream.prototype._flush = function(cb){
    42     this.push('Oh Yeah!')
    43     cb()
    44 }
    45 
    46 var rs = new ReadStream()
    47 var ws = new WriteStream()
    48 var ts = new TransformStream()
    49 
    50 rs.pipe(ts).pipe(ws)
  • 相关阅读:
    sqlite语法
    java 多态性
    Jekyll Bootstrap初始
    2019年 八年级下册期中总结
    2019年 八年级下册期中总结
    【洛谷P1415】拆分数列【dp】
    【洛谷P1415】拆分数列【dp】
    【洛谷P1197】星球大战【并查集】
    【洛谷P1197】星球大战【并查集】
    【P1261】服务器储存信息问题【最短路】
  • 原文地址:https://www.cnblogs.com/haoyijing/p/6478742.html
Copyright © 2020-2023  润新知