本文共 11629 字,大约阅读时间需要 38 分钟。
经过几天源码研究学习之后,基本上对Promise有了深入的了解,也手动封装了自己了Promise工具类,下面就是我们去在应用场景中去验证这个工具类的使用了
显示桌面通知的流程如下:
代码逻辑
const msgOpt = { body: '你今天还有需要完成的任务哦!', icon: 'http://7xi480.com1.z0.glb.clouddn.com/avatar100.jpg' } // 是否允许显示桌面通知 function requestNoti(){ return new MPromise( (resolve, reject)=>{ if(Notification.permission === 'granted'){ resolve() } else{ Notification.requestPermission( function (status) { if (Notification.permission !== status) { Notification.permission = status; } if (status === 'granted') { resolve() } else { reject( new Error( 'user denied')); } }); } }) } // 显示通知 function showNoti(msgObj){ return new MPromise( (resolve, reject)=>{ var n = new Notification( '通知',msgObj) // 3s钟之内,无论是用户点击还是超时未点击关闭,都将关闭通知 MPromise.timeout(closeNoti(), 3000).always( ()=>{ n.close(); resolve(); }) // 如果打开失败 reject 触发rejected回调 n.addEventListener( 'error', reject) function closeNoti(){ return new MPromise( rs => { n.addEventListener( 'click', rs) n.addEventListener( 'close', rs) }) } }) } // 开始 requestNoti() .then( ()=>{ console.log( '显示 桌面通知') return showNoti(msgOpt) }) .catch( ()=>{ console.log( '中断 不允许显示桌面通知') return MPromise.stop(); }) .then( ()=>{ console.log( '关闭 桌面通知') }) .catch( err=>{ console.log( '失败 桌面通知打开失败') }) |
这里API的应用
timeout()
用于限制2s钟之内,通知必须关闭 always()
与timeout结合使用 stop()
在promise链的中途停止后面的执行 这里为什么使用Deferred来封装异步请求呢?
因为使用new Promise()
的形式会有多一层嵌套,使用 deferred
可以对流程控制自由定制 function ajaxGet(URL) { var deferred = MPromise.deferred(); var req = new XMLHttpRequest(); req.open( 'GET', URL, true); req.onload = function () { if (req.status === 200) { deferred.resolve(req.responseText); } else { deferred.reject( new Error(req.statusText)); } }; req.onerror = function () { deferred.reject( new Error(req.statusText)); }; req.send(); var abort = function () { if (req.readyState !== XMLHttpRequest.UNSENT) { req.abort(); } }; return { promise: deferred.promise, abort: abort } } ajaxGet( 'd1.json').promise .then( res=> JSON.parse(res)) .catch( err=> console.log(err)) .then( res=> console.log(res)) |
发起一个异步请求,如果3s内还没有请求成功,则取消请求
var getData = ajaxGet( 'd1.json'); console.log( '显示loading') MPromise.timeout(getData.promise, 3000) .then( res=>{ return JSON.parse(res); }, err=>{ if(err instanceof window.TimeoutError){ getData.abort(); throw new Error( '请求超时,取消请求') } else{ throw err; } }) .then( res=>{ console.log( '请求成功: ', res); }) .always( ()=>{ console.log( '取消loading') }) .catch( err=>{ console.log(err) }) |
使用Promise对fs封装的好处是可以很方便的异步处理文件流,对错误可以集中式处理,如果是同步使用fs相关方法,错误处理将会变得复杂
var fs = require( "fs"); var MPromise = require( './promise_browser'); function File() { this.promise = MPromise.resolve(); } // Static method for File.prototype.read File.read = function (filePath) { var file = new File(); return file.read(filePath); }; File.prototype.then = function (onFulfilled, onRejected) { this.promise = this.promise.then(onFulfilled, onRejected); return this; }; File.prototype[ "catch"] = function (onRejected) { this.promise = this.promise.catch(onRejected); return this; }; File.prototype.read = function (filePath) { return this.then( function () { return fs.readFileSync(filePath, "utf-8"); }); }; File.prototype.transform = function (fn) { return this.then(fn); }; File.prototype.write = function (filePath) { return this.then( function (data) { return fs.writeFileSync(filePath, data) }); }; module.exports = File; |
使用
var File = require( "./fs-promise-chain"); var inputFilePath = "input.txt", outputFilePath = "output.txt"; File.read(inputFilePath) .transform( function (content) { return ">>" + content; }) .write(outputFilePath) .catch( function(err){ console.log(err) }) |
对于 nodejs 相关的异步处理,Q
或 bluebirde
都有相关的API用于包装成Promise对象,
例如 bluebirde
中可以使用 Promise.promisify
方法进行包装
var readFile = Promise.promisify( require( "fs").readFile); readFile( "myfile.js", "utf8").then( function(contents) { return eval(contents); }).then( function(result) { console.log( "The result of evaluating myfile.js", result); }).catch( SyntaxError, function(e) { console.log( "File had syntax error", e); //Catch any other error }).catch( function(e) { console.log( "Error reading file", e); }); |
这里还是建议大家使用 Q
或者 bluebirde
等相关成熟的Promise方案,本系列的Promise学习就到这里的,在此过程中封装的Promise工具类也主要用于学习和理解Promise的原理。
重点是我们掌握了Promise的使用之后,能更好的和ES7 的 Async/await
结合起来使用,那么以后的异步处理就更加得心应手了。
据说 node7.0 已经支持 Async/await
,让我们视目以待吧。
相关示例源码,请至 查看
http://coderlt.coding.me/2016/12/05/promise-in-depth-an-introduction-3/
转载地址:http://kueni.baihongyu.com/