首先用最簡單的方式實作一個動畫效果
<!doctype>
<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>
</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, cd){
//每13毫秒改變一次圓球的位置,直到到達指定位置
setTimeout(function(){
var marginLeft = parseInt(ball.style.marginLeft,10)
//球達到預期位置
if(marginLeft === distance){
cd && cd()
}else{
//球在左側
if(marginLeft < distance){
marginLeft++
}else{
//球在右側
marginLeft--
}
//調整球的位置
ball.style.marginLeft = marginLeft
animate(ball, distance, cd)
}
},13)
}
//控制動畫
animate(ball1, 100,function(){
animate(ball2, 200, function(){
animate(ball3, 150, function(){
animate(ball2, 150, function(){
animate(ball1, 150, function(){
})
})
})
})
})
</script>
</body>
</html>
使用promise實作相同功能
<!doctype>
<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 src="./node_modules/bluebird/js/browser/bluebird.js" type="text/javascript"></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>
<script type="text/javascript">
//定義三個球
var ball1 = document.querySelector('.ball1')
var ball2 = document.querySelector('.ball2')
var ball3 = document.querySelector('.ball3')
var Promise = window.Promise
function promiseAnimate(ball, distance){
return new Promise(function(resolve, reject){
//球,移動距離,回調函數
function _animate(){
//每13毫秒改變一次圓球的位置,直到到達指定位置
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, 150)
})
.then(function(){
return promiseAnimate(ball2, 150)
})
.then(function(){
return promiseAnimate(ball1, 150)
})
</script>
</body>
</html>
promise對象三種狀态:
- -未完成(pending)
- -已完成(fulfiled)
- -失敗(rejected)
promiseA與promiseA+不同點:
- -A+規範通過屬于thenable來區分promise對象
- -A+定義onFulfilled/onRejected必須是作為函數來調用,而且調用過程必須是異步的
- -A+嚴格定義了then方法鍊式調用時onFulfilled/onRejected的調用順序
promise then 方法
将異步執行的回調函數放入then方法中,規範鍊式書寫
promiseObj.then(onFunction, onRejected)
onFulfilled = function(value){
return promiseObj2
}
onRejected = function(err){}
promise庫有很多
- bluebird
- Q
- then.js
- es6-promise
- ypromise
- async
- native-promise-only
使用promise重寫爬蟲
對比:07慕課網《進擊Node.js基礎(一)》HTTP小爬蟲
var http = require('http')
var Promise = require('bluebird')
var cheerio = require('cheerio') //使用子產品
var baseUrl = 'http://www.imooc.com/learn/'
var videoIds = [728,637,348]
function filterChapters(html){
//可以像jQuery一樣使用
var $ = cheerio.load(html)
var chapters = $('.chapter')
var title = $('.clearfix h2').text()
var number = $('.js-learn-num').text()
// courseData = {
// title : title,
// number : 0,
// videos : [{
// chapterTitle:'',
// videos:[{
// title:'',
// id:''
// }]
// }
var courseData = {
title : title,
number : number,
videos : []
}
chapters.each(function(item){
var chapter = $(this)
var chapterTitle = chapter.find('h3').text()
var videos = chapter.find('.video').children('li')
var chapterData = {
chapterTitle :chapterTitle.trim(),
videos:[]
}
videos.each(function(item){
var video = $(this).find('a')
var videoTile = video.text()
var id = video.attr('href').split('video/')[1]
chapterData.videos.push({
title: videoTile.trim(),
id : id
})
})
courseData.videos.push(chapterData)
})
return courseData
}
function printCourseInfo(coursesData){
coursesData.forEach(function(courseData){
console.log(courseData.number + ' 人學過 ' + courseData.title + '\n')
})
coursesData.forEach(function(courseData){
console.log('###' + courseData.title + '\n')
courseData.videos.forEach(function(item){
var chapterTitle = item.chapterTitle
item.videos.forEach(function(video){
console.log(' 【' + video.id + '】' + video.title + '\n')
})
})
})
}
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('errer',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 curses = filterChapters(html)
coursesData.push(curses)
})
coursesData.sort(function(a,b){
return a.number < b.number
})
printCourseInfo(coursesData)
})
HTTP和HTTPS
HTTPS在http的基礎上進行了加密

運作HTTPS服務,.pem檔案還需要另外的方式建立
var https = require('https')
var fs = require('fs')
var options = {
key: fs.readFileSync('ssh_key.pem'),//ssl 檔案
key: fs.readFileSync('ssh_cert.pem'),//證書檔案
}
//運作HTTPS伺服器
https.createServer(options, function(req,res){
res.writeHead(200)
res.end('hello world'+ req)
}).listen(8090)