问题描述
Q:使用异步接口,实现递归遍历查找指定文件
异步的优势:
- 相较于同步接口,异步不阻塞主线程,速度更快。
- 相较于await,也更快。尤其是只有一个任务在执行的时候,await虽是异步,但是同一个任务中,是按照指令顺序执行的。
设计解决思路
- *异步的处理技巧是使用一个变量 asyncOps,标记当前正在进行的异步操作数量。**每次异步开始前,+1;结束后,-1。
- *当一个异步操作完成后,需要检查是否所有异步都完成,完成则触发回调函数。**每次-1 后,检查 asyncOps 是否为 0,如果为 0,那么所有异步都完成,触发回调函数。
为了防止错误回调函数重复触发,使用一个变量进行标识。
代码地址
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 
 | 
 
 
 
 
 const fs = require('fs')
 const join = require('path').join
 
 
 
 
 
 
 
 function find(nameRe, rootPath, callback) {
 const results = []
 let asyncOps = 0
 let errored = false
 
 finder(rootPath)
 
 
 
 
 
 function handleError(err) {
 if (errored) return
 errored = true
 callback(err)
 }
 
 
 
 
 function finder(path) {
 ++asyncOps
 
 fs.readdir(path, (err, files) => {
 if (err) return handleError(err)
 
 for (const file of files) {
 const fpath = join(path, file)
 
 ++asyncOps
 fs.stat(fpath, (err, stats) => {
 if (err) return handleError(err)
 
 if (stats.isDirectory()) {
 finder(fpath)
 } else if (stats.isFile() && nameRe.test(file)) {
 results.push(fpath)
 }
 
 --asyncOps
 
 if (!asyncOps) callback(null, results)
 })
 }
 
 --asyncOps
 if (!asyncOps) callback(null, results)
 })
 }
 }
 
 module.exports.find = find
 
 | 
使用效果
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | const { find } = require('./async-find')const path = require('path')
 
 const rootPath = path.join(
 __dirname,
 '..',
 '..',
 'algorithm'
 )
 
 find(/better/, rootPath, (err, results) => {
 if (err) throw err
 console.log(results)
 })
 
 |