使用 Q.js 库 Promise 真的取代 callback 了吗 本节演示代码 使用 Q.js 库 如果实际项目中使用Promise,还是强烈建议使用比较靠谱的第三方插件,会极大增加你的开发效率。除了将要介绍的Q.js,还有bluebird也推荐使用,去 github 自行搜索吧。 另外,使用第三方库不仅仅是提高效率,它还让你在浏览器端(不支持Promise的环境中)使用promise。 本节内容概述 下载和安装 使用Q.nfcall和Q.nfapply 使用Q.defer 使用Q.denodeify 使用Q.all和Q.any 使用Q.delay 其他 下载和安装 可以直接去它的 github 地址 (近 1.3W 的 star 数量说明其用户群很大)查看文档。 如果项目使用 CommonJS 规范直接 npm i q --save,如果是网页外链可寻找可用的 cdn 地址,或者干脆下载到本地。 以下我将要演示的代码,都是使用 CommonJS 规范的,因此我要演示代码之前加上引用,以后的代码演示就不重复加了。 const Q = require('q') 使用Q.nfcall和Q.nfapply 要使用这两个函数,你得首先了解 JS 的call和apply,如果不了解,先去看看。熟悉了这两个函数之后,再回来看。 Q.nfcall就是使用call的语法来返回一个promise对象,例如 const fullFileName = path.resolve(__dirname, '../data/data1.json') const result = Q.nfcall(fs.readFile, fullFileName, 'utf-8') // 使用 Q.nfcall 返回一个 promise result.then(data => { console.log(data) }).catch(err => { console.log(err.stack) }) Q.nfapply就是使用apply的语法返回一个promise对象,例如 const fullFileName = path.resolve(__dirname, '../data/data1.json') const result = Q.nfapply(fs.readFile, [fullFileName, 'utf-8']) // 使用 Q.nfapply 返回一个 promise result.then(data => { console.log(data) }).catch(err => { console.log(err.stack) }) 怎么样,体验了一把,是不是比直接自己写Promise简单多了? 使用Q.defer Q.defer算是一个比较偏底层一点的 API ,用于自己定义一个promise生成器,如果你需要在浏览器端编写,而且浏览器不支持Promise,这个就有用处了。 function readFile(fileName) { const defer = Q.defer() fs.readFile(fileName, (err, data) => { if (err) { defer.reject(err) } else { defer.resolve(data.toString()) } }) return defer.promise } readFile('data1.json') .then(data => { console.log(data) }) .catch(err => { console.log(err.stack) }) 使用Q.denodeify 我们在很早之前的一节中自己封装了一个fs.readFile的promise生成器,这里再次回顾一下 const readFilePromise = function (fileName) { return new Promise((resolve, reject) => { fs.readFile(fileName, (err, data) => { if (err) { reject(err) } else { resolve(data.toString()) } }) }) } 虽然看着不麻烦,但是还是需要很多行代码来实现,如果使用Q.denodeify,一行代码就搞定了! const readFilePromise = Q.denodeify(fs.readFile) Q.denodeify就是一键将fs.readFile这种有回调函数作为参数的异步操作封装成一个promise生成器,非常方便! 使用Q.all和Q.any 这两个其实就是对应了之前讲过的Promise.all和Promise.race,而且应用起来一模一样,不多赘述。 const r1 = Q.nfcall(fs.readFile, 'data1.json', 'utf-8') const r2 = Q.nfcall(fs.readFile, 'data2.json', 'utf-8') Q.all([r1, r2]).then(arr => { console.log(arr) }).catch(err => { console.log(err) }) 使用Q.delay Q.delay,顾名思义,就是延迟的意思。例如,读取一个文件成功之后,再过五秒钟之后,再去做xxxx。这个如果是自己写的话,也挺费劲的,但是Q.delay就直接给我们分装好了。 const result = Q.nfcall(fs.readFile, 'data1.json', 'utf-8') result.delay(5000).then(data => { // 得到结果 console.log(data.toString()) }).catch(err => { // 捕获错误 console.log(err.stack) }) 其他 以上就是Q.js一些最常用的操作,其他的一些非常用技巧,大家可以去搜索或者去官网查看文档。 至此,ES6 Promise的所有内容就已经讲完了。但是异步操作的优化到这里没有结束,更加精彩的内容还在后面 ———— Generator Promise 真的取代 callback 了吗 本节演示代码