问题描述
Q:使用异步接口,实现递归遍历查找指定文件
异步的优势:
- 相较于同步接口,异步不阻塞主线程,速度更快。
- 相较于await,也更快。尤其是只有一个任务在执行的时候,await虽是异步,但是同一个任务中,是按照指令顺序执行的。
设计解决思路
- *异步的处理技巧是使用一个变量 asyncOps,标记当前正在进行的异步操作数量。**每次异步开始前,+1;结束后,-1。
- *当一个异步操作完成后,需要检查是否所有异步都完成,完成则触发回调函数。**每次-1 后,检查 asyncOps 是否为 0,如果为 0,那么所有异步都完成,触发回调函数。
为了防止错误回调函数重复触发,使用一个变量进行标识。
代码地址
1 2 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
|
使用效果
1 2 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) })
|