8.NodeJs之小白初识promise

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);
  });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 特点 Promise能将回调分离出来,在异步操作执行之后,用链式方法执行回调,虽然es5用封装函数也能实现,但是如...
    一二三kkxx阅读 617评论 0 1
  • //本文内容起初摘抄于 阮一峰 作者的译文,用于记录和学习,建议观者移步于原文 概念: 所谓的Promise,...
    曾经过往阅读 1,231评论 0 7
  • 去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范。作为ES6...
    yzc123446阅读 283评论 0 1
  • Promise()讲解 Promise对象 Promise是一个构造函数 自己身上有all、reject、reso...
    贝灬小晖阅读 350评论 0 0
  • 我的成长是刻在你额头上的横杠;我的放纵是刻在你眉心的竖杠;我的欢乐是刻在你眼角的鱼尾;我的成功是刻在你唇边...
    未完的心梦阅读 264评论 0 2