-
流是事件的一個實例,stream是基于事件工作的,所以在流對象上具有異步的特征,可以監聽事件,觸發事件,流在各個階段的變化都可以被我們實時監聽
查看全部 -
// var http = require('http')
var https = require('https')
var Promise = require('bluebird')
var cheerio = require('cheerio')
var baseUrl = 'http://www.xianlaiwan.cn/learn/'
var url = 'http://www.xianlaiwan.cn/learn/348'
var videoIds = [348, 259, 197, 134, 75]
function filterChapters(html) {
var $ = cheerio.load(html)
var chapters = $('.chapter')
var title = $('hd h2').text()
var number = parseInt($('.js-learn-num').text())
// courseData = {
// ? ? title:title,
// ? ? number:number,
// ? ? videos:[{
// ? ? ? ? chapterTitle: '',
// ? ? ? ? videos: [
// ? ? ? ? ? ? title: '',
// ? ? ? ? ? ? id: ''
// ? ? ? ? ]
// ? ? }]
// }
var coursesData = {
title: title,
number: number,
videos: []
}
chapters.each(function (item) {
var chapter = $(this)
var chapterTitle = chapter.find('.chapter-description').text()
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()
var id = video.attr('href').split('video/')[1]
chapterData.videos.push({
title: videoTitle,
id: id
})
})
coursesData.videos.push(chapterData)
})
return coursesData
}
function printCourseInfo(coursesData) {
coursesData.forEach((courseData) => {
console.log(courseData.number) + '人學過' + courseData.title + '\n'
})
coursesData.forEach(courseData => {
console.log('###' + courseData.title + '\n')
courseData.videos.forEach((item) => {
var chapterTitle = item.chapterTitle
console.log(chapterTitle + '\n')
item.videos.forEach(video => {
console.log('【' + video.id + '】' + video.title + '\n')
})
})
});
}
function getPageAsync(url) {
return new Promise(function (resolve, reject) {
console.log("正在爬取" + url)
https.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 () {
console.log('獲取出錯')
reject(e)
})
})
}
var fetchCourseArray = []
videoIds.forEach((id) => {
fetchCourseArray.push(getPageAsync(baseUrl + id))
})
Promise.all(fetchCourseArray).then(function (pages) {
//
var courseData = []
pages.forEach(function (html) {
var courses = filterChapters(html)
courseData.push(courses)
})
courseData.sort((a, b) => {
return a.number < b.number
})
printCourseInfo(courseData)
})
查看全部 -
<!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</title>
<style>
.ball {
width: 40px;
height: 40px;
border-radius: 50%;
}
.ball1 {
background: red;
}
.ball2 {
background: yellow;
}
.ball3 {
background: green;
}
</style>
<script src="./node_modules/bluebird/js/browser/bluebird.js"></script>
</head>
<body>
<div class="ball ball1" ></div>
<div class="ball ball2" ></div>
<div class="ball ball3" ></div>
<script>
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((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>
</body>
</html>
查看全部 -
<!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</title>
<style>
.ball {
width: 40px;
height: 40px;
border-radius: 50%;
}
.ball1 {
background: red;
}
.ball2 {
background: yellow;
}
.ball3 {
background: green;
}
</style>
</head>
<body>
<div class="ball ball1" ></div>
<div class="ball ball2" ></div>
<div class="ball ball3" ></div>
<script>
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);
console.log(marginLeft);
console.log(distance)
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 () {})
})
})
})
})
})
</script>
</body>
</html>
查看全部 -
var?http?=?require('http'); var?https?=?require('https'); //var?Promise?=?require('Promise') var?Promise?=?require('bluebird') var?cheerio?=?require('cheerio'); var?baseUrl?=?'http://www.xianlaiwan.cn/learn/'; var?videoIds?=?[348,?259,?197,?134,?75]; function?filterChapters(html)?{ var?$?=?cheerio.load(html); var?chapters?=?$('.chapter.course-wrap'); var?title?=?$('.hd.clearfix?h2').text(); //console.log('###課程標題###:'?+?title); //var?number?=?parseInt($('.meta-value.js-learn-num').text()); //var?numberHtml?=?getHttpsPageAsync('http://www.xianlaiwan.cn/course/AjaxCourseMembers?ids=348'); //var?number?=?JSON.parse(getHttpsPageAsync('http://www.xianlaiwan.cn/course/AjaxCourseMembers?ids=348')).data[0].numbers; //console.log('###課程人數###:'?+?numberHtml); var?number?=?0; //var?courseData?=?[]; var?courseData?=?{ title:?title, number:?number, videos:?[] } chapters.each(function(item)?{ var?chapter?=?$(this) var?chapterTitle?=?chapter.find('h3').text(); //console.log('test:'?+?chapterTitle); 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(); //console.log('test:'?+?videoTitle); var?id?=?video.attr('href').split('video/')[1]; //console.log('test:'?+?id); 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?+?'\n'); }) coursesData.forEach(function(courseData)?{ console.log('###'?+?courseData.title?+?'\n'); courseData.videos.forEach(function(item)?{ var?chapterTitle?=?item.chapterTitle; console.log(chapterTitle.trim()?+?'\n'); item.videos.forEach(function(video)?{ console.log('【'?+?video.id?+?'】'?+?video.title.trim()?+?'\n'); }) }) }); } //生成爬取任務,將html作為Promise的resolve方法傳遞的值 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('獲取課程數據出錯'); }); }) } function?getHttpsPageAsync(url)?{ //return?new?Promise(function(resolve,?reject)?{ console.log('正在爬取?'?+?url) https.get(url,?function(res)?{ var?html?=?''; res.on('data',?function(data)?{ html?+=?data; }); console.log('https爬取'?+?html); res.on('end',?function()?{ return?html; //resolve(html) //var?courseData?=?filterChapters(html); //printCourseInfo(courseData); }); }).on('error',?function()?{ //reject(e); console.log('獲取課程數據出錯'); }); //}) } var?fetchCourseArry?=?[] videoIds.forEach(function(id)?{ fetchCourseArry.push(getPageAsync(baseUrl?+?id)) }) //等待所有網頁爬取任務完成后再進行filter操作,這時then里傳遞的是所有任務的resolve中傳遞值的數組? Promise .all(fetchCourseArry) .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); })
查看全部 -
Buffer和Stream是node的基礎能力查看全部
-
成果?(??????)?,也算入一點nodejs的門了吧, 感謝老師
查看全部 -
promise是一個對象,通過then方法可以鏈式編程,并且是在異步請求的基礎上,實現了同步操作then.
查看全部 -
promise庫
?bluebird, Q,
?then.js, es6-promise,?
ypromise, async,?
native-promise-only
查看全部 -
//之前的
<!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>
<style>
.ball {
width: 40px;
height: 40px;
border-radius: 50%;
}
.ball1 {
background-color: red;
}
.ball2 {
background-color: green;
}
.ball3 {
background-color: yellow;
}
</style>
</head>
<body>
<div>
<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>
</div>
</body>
</html>
<script>
var ball1 = document.querySelector('.ball1')
var ball2 = document.querySelector('.ball2')
var ball3 = document.querySelector('.ball3')
function animate(ball, distance, cb) {
setTimeout(function () {
// console.log(ball.style.marginLeft);
var marginLeft = parseInt(ball.style.marginLeft, 10)
// console.log(marginLeft);
if (marginLeft === distance) {
// 期望的點
cb && cb();
// animate(ball, distance, cb)
} else {
if (marginLeft > distance) {
// console.log(111);
marginLeft--;
} else {
marginLeft++;
}
// 改變樣式
ball.style.marginLeft = marginLeft + 'px';
animate(ball, distance, cb)
}
},10)
}
//
animate(ball1, 100, function () {
animate(ball2, 200, function () {
animate(ball3, 300, function () {
animate(ball3, 150, function () {
animate(ball2, 150, function () {
animate(ball1, 150, function () {
})
})
})
})
})
})
</script>
查看全部 -
一、stream種類
1、readable:
(1)reasume:流動模式
?(2)pause:暫停模式
2、writable
3、duplex:雙攻流,可讀可寫
tcp socket、zlip、queptal
4、transform:雙攻流,可讀可寫,轉換流
不保存數據
zlip、queptal
二、pipe
1、pipe方法會自動監聽data,err事件。
2、pipe方法可以自動控制后端壓力。
三、上一節的代碼可以簡寫成
var?fs?=?require('fs'); fs.createReadStream('websocket.gif').pipe(fs.createWriteStream('websoket-pipe.gif'));
查看全部 -
一、cat *.js | grep http 過濾包含Http的內容
二、buffer:保存原始數據
流:暫存和移動數據
三、涉及流的模塊:http、文件系統、壓縮模塊、tcpsocket、紫禁城標準式輸出。
流是buffer的形式存在。
四、拷貝時防爆倉處理
1、readStream的data中添加if。
2、writeSteam的drain處理。
var?fs?=?require('fs'); var?readStream?=?fs.createReadStream('websocket.gif'); var?writeSteam?=?fs.createWriteStream('websocket-stream.gif'); readStream.on('data',?function(chunk)?{ ??if(writeSteam.write(chunk)?===?false)?{ ????console.log('still?cached'); ????readStream.pause(); ??} ??//?writeSteam.write(chunk); }); readStream.on('end',?function()?{ ??writeSteam.end(); }); writeSteam.on('drain',?function()?{ ??console.log('data?drains'); ??readStream.resume(); })
查看全部
舉報