Node.jsWeb前端之路程序员

8.NodeJs之小白初识promise

2017-01-16  本文已影响199人  coderLfy

Promise入门级介绍


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

1. Promise到底是什么?

2. 为什么要用promise

3. promise 的属性和方法

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

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

这些状态只能从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)

7.PromiseA与A+不同点

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);
  });
上一篇下一篇

猜你喜欢

热点阅读