上面这段函数会遍历 listeners 中所有的listener(监听器) , 而listener 又是通过函数返回的对象 中的 onDataReady 方法添加的
传给 inconsistentRead 函数的第二个参数是一个回调函数, 它的执行时机 应该是等待所有的 onDataReady 方法执行完成再执行, 这样才有意义
inconsistentRead 是一个同步调用与异步调用混用的函数
- 如果
cache 中有值, 直接调用传入的回调函数 - 如果
cache 中没有值, 通过 readFile 读取传入的文件内容, 当获取到文件内容之后, 给 cache 设置值, 并调用回调函数
import { readFile } from 'fs'
const cache = new Map()
function inconsistentRead(filename, cb) {
if (cache.has(filename)) {
cb(cache.get(filename))
} else {
readFile(filename, 'utf8', (err, data) => {
cache.set(filename, data)
cb(data)
})
}
}
function createFileReader(filename) {
const listeners = []
inconsistentRead(filename, value => {
listeners.forEach(listener => listener(value))
})
return {
onDataReady: listener => listeners.push(listener)
}
}
const reader1 = createFileReader('data.txt')
reader1.onDataReady(data => {
console.log(`123 call data: ${data}`)
})
reader1.onDataReady(data => {
console.log(`456 call data: ${data}`)
})
reader1.onDataReady(data => {
console.log(`789 call data: ${data}`)
const reader2 = createFileReader('data.txt')
reader2.onDataReady(data => {
console.log(`Second call data: ${data}`)
})
})
输出结果如下: reader2.onDataReady 内的回调未执行
所以, 一个函数中, 要么全是同步, 要么全是异步
同步读取函数
function consistentReadSync (filename) {
if (cache.has(filename)) {
return cache.get(filename)
} else {
const data = readFileSync(filename, 'utf8')
cache.set(filename, data)
return data
}
}
console.log(consistentReadSync('data.txt'))
console.log(consistentReadSync('data.txt'))
异步读取函数
import { readFile } from 'fs'
const cache = new Map()
function consistentReadAsync(filename, callback) {
if (cache.has(filename)) {
process.nextTick(() => callback(cache.get(filename)))
} else {
readFile(filename, 'utf8', (err, data) => {
cache.set(filename, data)
callback(data)
})
}
}
function createFileReader(filename) {
const listeners = []
consistentReadAsync(filename, value => {
listeners.forEach(listener => listener(value))
})
return {
onDataReady: listener => listeners.push(listener)
}
}
const reader1 = createFileReader('data.txt')
reader1.onDataReady(data => {
console.log(`123 call data: ${data}`)
})
reader1.onDataReady(data => {
console.log(`456 call data: ${data}`)
})
reader1.onDataReady(data => {
console.log(`789 call data: ${data}`)
const reader2 = createFileReader('data.txt')
reader2.onDataReady(data => {
console.log(`Second call data: ${data}`)
})
})
来自 <Nodejs设计模式-第三版> 第三章-回调与事件
|