res.statusCode !== 200) ? true : false
const getImgUrls = function (pages) {
return new Promise((resolve) => {
let limit = 8, number = 0, imgUrls = []
const recursive = async function () {
pages = pages - limit
limit = pages >= 0 ? limit : (pages + limit)
let arr = []
for (let i = 1; i <=limit; i++) {
arr.push(
new Promise((resolve) => {
request(target + `?set=${number++}`, (err, res, data) => {
if (isError(err, res)) return console.log('Request failed.')
let $ = cheerio.load(data)
$('.pg-page-wrapper img').each((i, el) => {
let imgUrl = $(el).attr('data-cfsrc')
imgUrls.push(imgUrl)
resolve()
})
})
})
)
}
await Promise.all(arr)
if (limit === 8) return recursive()
resolve(imgUrls)
}
recursive()
})
}
const downloadImages = function (imgUrls) {
console.log('\n Start to download images. \n')
let limit = 5
const recursive = async function () {
limit = imgUrls.length - limit >= 0 ? limit : imgUrls.length
let arr = imgUrls.splice(0, limit)
let promises = arr.map((url) => {
return new Promise((resolve) => {
let imgName = url.split('/').pop()
let imgPath = path.join(__dirname, `images/${imgName}`)
request(url)
.pipe(fs.createWriteStream(imgPath))
.on('close', () => {
console.log(`${imgName} has been saved.`)
resolve()
})
})
})
await Promise.all(promises)
if (imgUrls.length) return recursive()
console.log('\n All images have been downloaded.')
}
recursive()
}
request({
url: target,
method: 'GET'
}, (err, res, data) => {
if (isError(err, res)) return console.log('Request failed.')
let $ = cheerio.load(data)
let pageNum = $('.pg-pagination li').length
console.log('Start to get image urls...')
getImgUrls(pageNum)
.then((result) => {
console.log(`Finish getting image urls and the number of them is ${result.length}.`)
downloadImages(result)
})
})
发布 / 订阅模式
我们假定,存在一个"信号中心",当某个任务执行完成,就向信号中心"发布" ( publish ) 一个信号,其他任务可以向信号中心"订阅" ( subscribe ) 这个信号,从而知道什么时候自己可以开始执行,当然我们还可以取消订阅这个信号。
我们先来实现一个简单的发布订阅对象:
class Listener {
constructor() {
this.eventList = {}
}
on(event, fn) {
if (!this.eventList[event]) this.eventList[event] = []
if (fn.name) {
let obj = {}
obj[fn.name] = fn
fn = obj
}
this.eventList[event].push(fn)
}
remove(event, fn) {
if (!fn) return console.error('Choose a named function to remove!')
this.eventList[event].map((item, index) => {
if (typeof item === 'object' && item[fn.name]) {
this.eventList[event].splice(index, 1)
}
})
}
emit(event, data) {
this.eventList[event].map((fn) => {
if (typeof fn === 'object') {
Object.values(fn).map((f) => f.call(null, data))
} else {
fn.call(null, data)
}
})
}
}
let listener = new Listener()
function foo(data) { console.log('Hello ' + data) }
listener.on('click', (data) => console.log(data))
listener.on('click', foo)
listener.emit('click', 'RetroAstro')
// Hello
// Hello RetroAstro
listener.remove('click', foo)
listener.emit('click', 'Barry Allen')
// Barry Allen场景三:
监听 watch 文件夹,当里面的文件有改动时自动压缩该文件并保存到 done 文件夹中。
// gzip.js
const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const gzipFile = function (file) {
let dir = path.join(__dirname, 'watch')
fs.readdir(dir, (err, files) => {
if (err) console.error(err)
files.map((filename) => {
let watchFile = path.join(dir, filename)
fs.stat(watchFile, (err, stats) => {
if (err) console.error(err)
if (stats.isFile() && file === filename) {
let doneFile = path.join(__dirname, `done/${file}.gz`)
fs.createReadStream(watchFile)
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream(doneFile))
}
})
})
})
}
module.exports = {
gzipFile: gzipFile
}开始监听 watch 文件夹
// watch.js
const fs = require('fs')
const path = require('path')
const { gzipFile } = require('./gzip')
const { Listener } = require('./listener')
let listener = new Listener()
listener.on('gzip', (data) => gzipFile(data))
let dir = path.join(__dirname, 'watch')
let wait = true
fs.watch(dir, (event, filename) => {
if (filename && event === 'change' && wait) {
wait = false
setTimeout(() => wait = true, 100)
listener.emit('gzip', filename)
}
})结语
对于 JavaScript 异步编程在这里我就讲这么多了,当然还有很多东西自己没有了解和学习到,因此在本篇文章中没有涉及。最后还是给出上面三个场景代码的 GitHub 地址 ,总之在前端学习的路上还得继续加油嘞 。
以上就是JavaScript异步编程的详细介绍(附示例)的详细内容,更多请关注php中文网其它相关文章!
网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。
关键词:JavaScript异步编程的详细介绍(附示例)