该迭代已作废,最新的请移步这里:https://www.cnblogs.com/GerryOfZhong/p/10726306.html

距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这个行业,让大脑休息一下。一个人旅行,一个人休息,正好也去完成一个目标 --- 拥有自己的驾照。当然,也把自己晒的黑漆马虎的。不过这一段时间虽然在技术上没有学太多东西,但是在心态上给了自己一个沉淀的机会,感觉自己变得更加沉稳和成熟,感觉这就是自己需要找到的自己,回归自我。好了,废话不多说了,虽然技术上没有学一些新的东西,但是欠的东西还是要补回来的。正如这篇博客,前端Promise规范的实现与ajax技术的集成,当时github上一个用户提的,既然写了ajax,那么Promise的规范,更优雅的操作异步也应该有的,当时记下了,现在补回来。回归正题,下面介绍一些概念。

  • Promise   ES6中最重要的特性之一,就是代表了未来某个将要发生的事件(通常是一个异步操作)。它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
  • js对象的继承和传递  在js中是没有所谓的继承概念的,继承通常是指后台面向对象编程中对象之间的复用。因为js被叫做脚本语言,所以没有这个概念,但是在js中都可以模拟实现的(apply,call,prototype)。其实说通俗点所谓的继承就是作用域的传递。
  • ajax和promise的缘分  因为ajax是一个异步的请求(虽然也可以使用同步),而promise这个状态机也正好可以处理异步操作。两者的相结合的产物,将是一个优雅而又快捷的产物,这个将在后面的介绍中展现。

工具准备:

    1. 前端代码,自己实现的promise规范代码,以及集成现有es6规范的代码。

    2. nginx服务器,做分离,反向代理后台代码

    3. IIS服务器,部署后台请求(模拟一般请求和高延迟请求)

    4. 各大兼容和不兼容promise的浏览器(做测试)

前端Promise代码实现:

/*** Created by gerry.zhong on 2017/6/21.*/
var Promise = function(fn){var promise = this;//状态机的状态var PROMISESTATE = {PENDING : 0 ,FULFILLED : 1 ,REJECTED : 2};//存储当前变量的回调函数和标记对象为promisepromise._fullCalll =[],promise._rejCall = [];promise._name = "promise";//执行过程中的状态变化(初始化状态为默认状态)var _state =  PROMISESTATE.PENDING;//回调函数的参数var _value = undefined;//状态变更function setState(stateT,valueT){var promise = this;_state = stateT;_value = valueT;handleFun.call(promise);  //传递作用域,并且执行回调函数
    };//根据状态处理回调function handleFun(){var promise = this,isThen;if (_state === PROMISESTATE.FULFILLED &&typeof promise._fullCalll[0] === 'function') {isThen = promise._fullCalll[0](_value);};if (_state === PROMISESTATE.REJECTED &&typeof promise._rejCall[0] === 'function') {isThen = promise._rejCall[0](_value);};//对于是否可以继续进行then做判断//  1. 不可then的,直接return结束(条件:无返回值、返回值不是promise对象的)//  2. 对于可以then的,将then的回调进行处理,然后对象之间传递。if (isThen === undefined || !(typeof isThen === 'object' && isThen._name === 'promise')) return;promise._fullCalll.shift(); promise._rejCall.shift();      //清除当前对象使用过的对调isThen._fullCalll =promise._fullCalll;isThen._rejCall = promise._rejCall;  //将剩下的回调传递到下一个对象
    };//promimse入口function doResolve(fn){var promise = this;fn(function(param) {setState.call(promise,PROMISESTATE.FULFILLED,param);}, function(reason) {setState.call(promise,PROMISESTATE.REJECTED,reason);});};//函数then,处理回调,返回对象保证链式调用this.then = function(onFulfilled,onRejected) {this._fullCalll.push(onFulfilled);this._rejCall.push(onRejected);return this;}doResolve.call(promise,fn);
}

具体思路如下:

解决浏览器的差异性和兼容性代码

if (!window.Promise) tool.createPromise();  //保证浏览器的兼容性

tool.createPromise代码

//如果浏览器不支持Promise特性,将用简易的promise代替(IE11-都不支持ES6 Promise)createPromise:function(){var newPromise = function(fn){var promise = this;//状态机的状态var PROMISESTATE = {PENDING : 0 ,FULFILLED : 1 ,REJECTED : 2};//存储当前变量的回调函数和标记对象为promisepromise._fullCalll =[],promise._rejCall = [];promise._name = "promise";//执行过程中的状态变化(初始化状态为默认状态)var _state =  PROMISESTATE.PENDING;//回调函数的参数var _value = undefined;//状态变更function setState(stateT,valueT){var promise = this;_state = stateT;_value = valueT;handleFun.call(promise);  //传递作用域,并且执行回调函数
                };//根据状态处理回调function handleFun(){var promise = this,isThen;if (_state === PROMISESTATE.FULFILLED &&typeof promise._fullCalll[0] === 'function') {isThen = promise._fullCalll[0](_value);};if (_state === PROMISESTATE.REJECTED &&typeof promise._rejCall[0] === 'function') {isThen = promise._rejCall[0](_value);};//对于是否可以继续进行then做判断//  1. 不可then的,直接return结束(条件:无返回值、返回值不是promise对象的)//  2. 对于可以then的,将then的回调进行处理,然后对象之间传递。if (isThen === undefined || !(typeof isThen === 'object' && isThen._name === 'promise')) return;promise._fullCalll.shift(); promise._rejCall.shift();      //清除当前对象使用过的对调isThen._fullCalll =promise._fullCalll;isThen._rejCall = promise._rejCall;  //将剩下的回调传递到下一个对象
                };//promimse入口function doResolve(fn){var promise = this;fn(function(param) {setState.call(promise,PROMISESTATE.FULFILLED,param);}, function(reason) {setState.call(promise,PROMISESTATE.REJECTED,reason);});};//函数then,处理回调,返回对象保证链式调用this.then = function(onFulfilled,onRejected) {this._fullCalll.push(onFulfilled);this._rejCall.push(onRejected);return this;}doResolve.call(promise,fn);};window.Promise = newPromise;},

这样就保证了,不管在兼容和不兼容Promise的浏览器中,都可以使用Promise,优雅的来操作异步了。

ajax集成proise代码(默认只开放了post和get方法,其他可自己拓展)

     //集成promise的ajax请求(默认设置post和get请求,如有其他需求,可自己拓展)promiseAjax:function (url,data,type){if (!window.Promise) tool.createPromise();  //保证浏览器的兼容性return new Promise(function(resolve, reject){if (type === undefined) ajax.post(url,data,resolve,reject);else ajax.get(url,data,resolve,reject);});},

测试环节

  对于网上很多人写的Promise代码仔细观摩和研究,发现很多问题。

    a. 对于并发Promise,会出现异步错乱,发起者和接受者错乱

    b. 对于多then的情况,异步响应的不确定(高低延迟),错乱。

    c. Promise代码实现的复杂性,多繁琐,难理解,思路不明确。

  针对以上问题,进行重要测试。

测试前端代码

    ajax.promiseAjax("api/ajax/postReq/",{"name":"q","age": 2}).then(function(value){console.log("一般请求q"+value);return ajax.promiseAjax("api/ajax/postReqSleep/",{"name":"w","age": 2});}).then(function(value){console.log("高延迟请求w:"+value);return ajax.promiseAjax("api/ajax/postReq/",{"name":"r","age": 2});}).then(function(value){console.log("一般请求r:"+value);});ajax.promiseAjax("api/ajax/postReqSleep/",{"name":"q1","age": 2}).then(function(value){console.log("高延迟请求q1"+value);return ajax.promiseAjax("api/ajax/postReqSleep/",{"name":"w2","age": 2});}).then(function(value){console.log("高延迟请求w2:"+value);return ajax.promiseAjax("api/ajax/postReq/",{"name":"r3","age": 2});}).then(function(value){console.log("一般请求r3:"+value);});

后端模拟延迟请求代码(C#)

        [Route("postReqSleep")]public string postRequestTSleep([FromBody]Param param){Thread.Sleep(5000);   //挂起5s 做延迟String result = "post请求成功:" + param.name + "-" + param.age;return result;}

测试结果:

  chrome

  ie8-11

  edge

  firefox

  360浏览器

  safair

代码已集成github:https://github.com/GerryIsWarrior/ajax     点颗星星是我最大的鼓励,有什么问题可以博客、邮箱、github上留言

还有最重要的一点,如果有问题欢迎指出来,我在github上维护这个库,这段时间专注于前端的通信技术的研究,ajax基本完成,马上进入SSE推送技术研究状态

研究Promise这个内容,研究和参考了很多别人的代码,从高别人的代码中看到了各种问题,然后在自己代码中测试发现和改正。所以没有什么是绝对正确的,我写的可能也有问题,希望大家在研究和发展的基础上一起改进。毕竟对于前端来说,技术更新太快,ES5 ES6等等一层接一层。还是那句老话,革命尚未成功,同志仍需努力,我和你们同在。

马上又要回去重新找工作了,希望可以找到如意的工作,毕竟为了错开金三银四,希望一切都会好起来。一起加油吧。

转载于:https://www.cnblogs.com/GerryOfZhong/p/7096792.html

前端通信:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码(改迭代已作废,移步迭代10)...相关推荐

  1. Spring Boot 集成 JUnit5,更优雅单元测试!

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://mp.weixin.qq.com/s/2Kdu-nYLF55Ui9A1-ybgFw 为什么使用JUnit5 J ...

  2. 如何让你的代码变得更优雅?这些代码规范和技巧必须知道(进阶必备,建议收藏)

    如何做一名优秀的程序猿?从改善每一行代码开始 1. 看你的代码就知道你几斤几两 2. 编程标准 3. 命名规范 4. 松耦合,高复用 5. 函数优化 6.条件优化 7. 循环优化 8. 如何提升js性 ...

  3. 前端通信:ajax设计方案(十)--- 完善Promise A+规范,增加mock数据功能

    同步更新博客: www.cnblogs.com/GerryOfZhon- 同步更新专栏: zhuanlan.zhihu.com/zhongqiang 同步更新github: github.com/Ge ...

  4. 前端通信:ajax设计方案(三)--- 集成ajax上传技术

    在此之前让我感慨一下现在的前端开发的氛围.我遇到好多人,给我的观念都是,这个东西这个框架有了,那个东西那个框架做了,前端嘛,学几个框架,这个拼凑一下那个拼凑一下就好了.其实我想问,东西都框架做了,那你 ...

  5. 通信总线协议五 :CAN

    文章目录 通信总线协议五 :CAN 1. CAN总线简介 2. CAN总线基本概念 3. CAN 协议介绍 3. 1 CAN 协议消息报文格式 3. 2 总线仲裁(Bus Arbitration) 3 ...

  6. 小蓝同学的前端之旅--HTML\CSS集成复习

    小蓝同学的前端之旅--HTML\CSS集成复习 前端学习路线 复习模式 api的重要性 HTML基础总结 head标签的常用标签 body标签中常用标签 文本元素标签 表格标签 表格分组 框架 表单 ...

  7. 大白话讲解Promise(二)理解Promise规范

    上一篇我们讲解了ES6中Promise的用法,但是知道了用法还远远不够,作为一名专业的前端工程师,还必须通晓原理.所以,为了补全我们关于Promise的知识树,有必要理解Promise/A+规范,理解 ...

  8. 掌握Ajax 第五部分 参考资料

    学习 您可以参阅本文在 developerWorks 全球站点上的 英文原文. 学习介绍 Ajax 的本 developerWorks 系列的前几篇文章: "掌握 Ajax,第 1 部分:A ...

  9. 千峰Ajax【fetch和promise】

    promise基础 <script>// Promise构造函数var q = new Promise(function (resolve, reject) {//异步setTimeout ...

最新文章

  1. 转 从头到尾彻底解析Hash表算法
  2. python找出值为nan_Python Numpy:找到list中的np.nan值方法
  3. Golang 学习笔记(安装)
  4. 基于FPGA的图像增强系统的verilog开发(3000+字)
  5. 【NLP】PET——文本分类的又一种妙解
  6. 论文理解 R-FCN:基于区域的全卷积网络来检测物体
  7. 靶场练习第二十天~vulnhub靶场之Funbox: Scriptkiddie
  8. c#完美截断字符串(中文+非中文)
  9. C# Regex 深入正则表达式
  10. Go程序:演示数组切片用法
  11. 结果出来了!视觉中国被罚30万 再次发布道歉声明...
  12. 特斯拉CEO马斯克:将离开推特一段时间
  13. .net 编译、反编译、查壳、脱壳、反混淆工具
  14. MATLAB (2014b) “doc” cannot load libxul.so from Java on Linux system解决办法
  15. html5红外遥控,自己写的单片机万能红外遥控解码
  16. 救命稻草VirtualBox,失之交臂VMware—— 2者的guest OS对 恒通笔记本并口卡的支持
  17. laravel实现汉子转拼音
  18. 2019 8 9 STM32F407ADS1526连续转换模式相关配置(采样率达到15000SPS)
  19. outlook客户端怎么看html,谷歌浏览器根据html网页启动邮件客户端Outlook(示例代码)...
  20. cyusb3014的slavefifo程序的解读

热门文章

  1. gsonformat插件_吐血推荐珍藏的IDEA插件
  2. AndroidJava try-catch-finally正确用法
  3. 微信公众号关注用户的信息拉取
  4. 怎么打包图片_怎么将许多张照片打包发到邮箱?
  5. html 自定义打印模板,HTML+CSS入门 自定义模板详解
  6. 华硕和梅林系统哪个好_RUSHCRM:定制CRM软件系统哪个好?
  7. php对mysql的操作教程,php与Mysql的一些简单的操作
  8. 椭圆极点极线性质_又见阿氏圆——适合作椭圆大题的小题
  9. tcpsyn发生在哪层_必看面试题之计算机网络:来自一位拿到了腾讯和字节双offer的大佬...
  10. python矩阵运算dot_numpy中的dot矩阵乘法