深入理解 Promise (下)
来源:互联网 发布:电子名片制作软件 编辑:程序博客网 时间:2024/05/16 19:42
经过几天源码研究学习之后,基本上对Promise有了深入的了解,也手动封装了自己了Promise工具类,下面就是我们去在应用场景中去验证这个工具类的使用了
上 - 理论知识
- Promise 规范
- ES6 Promise API
- Polyfill和扩展类库
- Promise 在应用中的错误用法和误区
- 当作回调使用
- 没有返回值
- 没有catch
- catch()与then(null, onRejected)
- 断链
- 穿透
- 长度未知的串行与并行
- Promise.resolve的使用
- 最佳实践
中 - 手动封装
- 实现一个简单的 Promise工具类
- Promise类的结构
- 构造器的初始化
- then方法
- catch方法
- 添加扩展功能函数
- all
- race
- resolve
- reject
- wait
- stop
- always
- done
- defer
- timeout
- sequence
- 测试
- 源码
下 - 实践应用
- 结合应用场景使用Promise
- 使用Promise编写Web Notifications提示
- 使用Deferred封装异步请求
- 异步请求的超时处理
- 基于Promise的fs方法链
Web Notifications提示
显示桌面通知的流程如下:
- 用户进入页面要判断是否默认允许显示桌面通知
- 如果不允许,提示是否允许
- 如果点击了允许,则显示通知
- 如果点击了拒绝,则不显示,后面的任务不执行
- 显示通知失败,则打印显示失败的信息
- 显示成功,判断用户是否点击了通知或点击了关闭
- 如果点击了,则关闭通知
- 如果没有点击,则2s之后自动关闭
- 关闭之后打印消息
代码逻辑
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封装异步请求
这里为什么使用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方法链
使用Promise对fs封装的好处是可以很方便的异步处理文件流,对错误可以集中式处理,如果是同步使用fs相关方法,错误处理将会变得复杂
var fs = require("fs");var MPromise = require('./promise_browser');function File() {this.promise = MPromise.resolve();}// Static method for File.prototype.readFile.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
,让我们视目以待吧。
相关示例源码,请至 MPromise 查看
http://coderlt.coding.me/2016/12/05/promise-in-depth-an-introduction-3/
- 深入理解 Promise (下)
- 深入理解 Promise (下)
- 深入理解promise
- 深入理解 Promise (上)
- 深入理解 Promise (中)
- 深入理解Promise
- 深入理解 Promise (上)
- 深入理解 Promise (中)
- 深入理解Promise
- Promise深入理解
- 深入理解JavaScript的Promise
- 深入理解JS异步编程三(promise)
- 深入理解 promise(完全转载)
- 深入理解javascript之初识promise
- 深入理解 Promise 五部曲:5. LEGO
- 深入理解 Promise 五部曲:3. 可靠性问题
- 深入理解 Promise 五部曲:4. 扩展问题
- 理解,promise~~
- 《操作系统》第12章:文件管理
- 机器学习:SVM作业编程实现(一)
- 利用js实现 禁用浏览器后退
- 深入理解 Promise (中)
- angular中CheckBox二维数组传值问题
- 深入理解 Promise (下)
- UIDevice 获取设备相关信息备忘
- 解决WAP端用Dreamweaver画热点偏移现象
- ES6笔记
- VC调用Matlab生成的c
- ES6笔记
- wxpython实现简单图书管理系统
- ZJCOJ 朋友Z与方程(二分求解模板题)
- java创建对象:new和newInstance的不同