8.NodeJs之小白初识promise

作者: coderLfy | 来源:发表于2017-01-16 16:37 被阅读199次

    Promise入门级介绍


    本文是观看了慕课网上的进击的NodeJs(二)后写的小结,感谢Scott老师

    1. Promise到底是什么?

    2. 为什么要用promise

    • 因为是ES6规范中的一个重要对象,学习没有坏处!
    • promise是为了处理回调地狱的新的处理
    • 让代码简洁,增加可读性的一种方式

    3. promise 的属性和方法

    首先介绍一下promise有几种状态:

    new Promise(/ * executor * / function(resolve,reject){...});

    • pedding: 一开始创建promise时的状态,不属于成功与失败
    • Resolved(成功状态)
    • rejected(失败)

    这些状态只能从pedding到成功,或者pending到失败,不可逆,不可停止;

    4. promise 的属性与方法

    属性:

    Promise.length
    Length属性,其值始终为1(构造函数参数的数目)

    Promise.prototype
    表示 Promise 构造器的原型.

    方法:

    1. Promise.all(iterable)
      返回一个Promise,当可迭代参数中的所有promise都满足或拒绝时,只要可迭代参数中的一个promise拒绝就满足。如果返回的promise满足,则使用来自履行的promise中的值的数组来实现,其具有与可迭代中定义的顺序相同的顺序。如果返回的promise拒绝,它被拒绝的原因来自可迭代的第一个promise拒绝。此方法可用于聚合多个promise的结果。
    1. Promise.race(iterable)
      返回一个promise,只要promise中的一个promise满足或拒绝,就满足或拒绝该promise,以及该promise中的值或原因。
    1. Promise.reject(reason)
      返回一个Promise被拒绝,并给出的理由对象。
    1. Promise.resolve(value)
      返回Promise一个与给定值解析的对象。如果该值是一个thenable(即有一个then方法),返回的承诺将“跟随 ”是thenable,采用其最终状态; 否则返回的promise将使用该值来完成。一般来说,如果你不知道一个值是一个承诺或没有,Promise.resolve(value)它反而和返回值作为一个承诺工作。

    5. 怎么用promise

    先从一个例子来了解一下回调地狱的感觉= =

    这个例子是三个小球的移动的例子,以注释的方式来解释例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>promise animation</title>
      <--这里是引入bluebird,我注释掉后一样可以使用Promise,因为现在的浏览器本身可以识别Promise 在node中要require('promise')-->
      <!-- <script src="./node_modules/bluebird/js/browser/bluebird.js" charset="utf-8"></script> -->
      <style media="screen">
        .ball{
          width: 40px;
          height: 40px;
          border-radius: 50%;
        }
        .ball1{
          background: red;
        }
        .ball2{
          background: blue;
        }
        .ball3{
          background: green;
        }
      </style>
    </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>
    
    <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() //这里是短路表达式,cb存在?执行cb()
      //     }else{
      //       if (marginLeft < distance){
      //           marginLeft++;
      //       }else{
      //         marginLeft--;
      //       }
      //       ball.style.marginLeft = marginLeft +'px';
      //       animate(ball, distance, cb);
      //     }
      //   },13)
      // }
    
    //callback回调函数的嵌套
      // animate(ball1, 100, function(){
      //   animate(ball2, 200, function(){
      //     animate(ball3, 300, function(){
      //       animate(ball3, 150, function(){
      //         animate(ball2, 150,function(){
      //           animate(ball1, 150, function(){
      //
      //           });
      //         });
      //       });
      //     });
      //   });
      // });
    
    
    
    
    /* 这是以Promise的形式 */
    var Promise = window.Promise;
    function promiseAnimate(ball, distance){
        //把promise对象返回
      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()
    
      })
    }
    //then有点类似类似链式调用,这种方式看着简洁,代码可读性高
    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>
    </body>
    </html>
    
    

    6. promise库(Scott老师推荐bluebird)

    • 以下promise库大同小异,学习期间重点是学习promise用法,各个差异自行百度,最新的浏览器都支持了promise,学习的时候也可以不用引库
    • bluebird
    • Q
    • then.js
    • es6-promise
    • ypromise
    • async
    • native-promise-only
    • .....

    7.PromiseA与A+不同点

    • A+ 规范通过术语thenable来区分promise对象
    • A+ 定义了onFulfilled/onRejected必须是作为函数来调用的,而且调用过程必须是异步
    • A+ 严格定义了then 方法链式调用时onFulfilled/onRejected的调用顺序

    8.Promise then方法

    promise会保证回调的顺序,链式调用then方法参数里的回调函数会依次调用,这then方法不会立即执行,只有前面的promise成功后才会进行

    promiseObj.then(onFulfilled,onRejjected){
        onFunlilled = function(value){
            return promiseObj2
        }
        inRejected = function(err){
            
        }
    }
    

    9. 简单HTTPS服务器的搭建

    http与https

    HTTPS是在HTTP的多了一层SSL/TLS,多了一次握手从三次握手改成了四次握手,这里就不多聊,有兴趣可以多多百度,主要是为了学习怎么搭建一个HTTPS的本地服务器

    var https = require('https');
    var fs = require('fs');//注入读取文件
    
    //key与cert
    var options = {
      key:fs.readFileSync('ssh_key.pem'),
      cert:fs.readFileSync('ssh_cert.pem')
    };
    
    https
      .createServer(options,function(req, res){
        res.writeHead(200);
        res.end('hello');
      })
      .listen(8080);
    
    

    10. 用promise优化爬虫

    在最新的版本里已经有了Promise这个函数了,老板本是没有这个函数的!要加第三方!

    var http = require('http');
    var cheerio = require('cheerio');//引入cheerio
    //新版本内置Promise了
    var baseUrl = 'http://www.imooc.com/learn/';
    // var url = 'http://www.imooc.com/learn/348';
    var videoIds = [348, 259, 197, 134, 75];
    function filterChapters(html){
      var $ = cheerio.load(html);//变成jq模样便于理解
      var chapters = $('.chapter');
      var title = $('#main .path span').text();
      //由于该爬虫只能爬到源代码上的数据,而人数又是ajax获取的,所以人数拿不到
    // courseData = {
    // title:title,
    //  videos:[{
    //     chapterTitle:'',
    //     videos:[{
    //       title:'',
    //       id:''
    //     }]
    //   }]
    // }
      var courseData = {
        title:title,
        videos:[]
      };
      chapters.each(function(item){
        var chapter = $(this);
        var chapterTitle = chapter.find('strong').text();
        var videos = chapter.find('.video').children('li');
        var chapterData= {
          chapterTitle:chapterTitle,
          videos:[]
        };
        videos.each(function(){
          var video = $(this).find('.J-media-item');
          var videoTitle = video.text();
          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.title + '\n');
        courseData.videos.forEach(function(item){
          var chapterTitle = item.chapterTitle;
          // console.log(chapterTitle + '\n');
          console.log(chapterTitle.replace(/\s+/g,"")+"\n");
          item.videos.forEach(function(video){
            // console.log('【' + video.id +'】' + video.title + '\n');
            console.log("【"+ video.id.replace(/\s+/g,"") +"】"+video.title.replace(/\s+/g,"") +"\n");
          });
        });
      });
    }
    function getPageAsync(url){
      return new Promise(function(resolve, reject){//返回一个Promise对象
          console.log('正在爬取 '+ url);
          http.get(url,function(res){
            var html = '';
            res.on('data',function(data){//data事件
              html += data;
            });
            res.on('end',function(){//end 事件
              resolve(html);//成功获取
            });
          }).on('error',function(e){//error
            reject(e);//失败
            console.log('获取课程数据失败!');
          });
      });
    }
    var fetchCourseArray = [];//存放Promise对象的数组
    videoIds.forEach(function(id){
      fetchCourseArray.push(getPageAsync(baseUrl + id));
    });
    Promise
      .all(fetchCourseArray)//等待所有的异步爬取结束以后利用then方法进行下一步
      .then(function(pages){
        var coursesData = [];
        pages.forEach(function(html){
          var courses = filterChapters(html);
            coursesData.push(courses);
        });
        printCourseInfo(coursesData);
      });
    

    相关文章

      网友评论

        本文标题:8.NodeJs之小白初识promise

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