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

 该迭代已作废,最新的请移步这里: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之 - 代理模式(Proxy Pattern)

代理模式:代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。很多可以框架中都有用到,比…

JavaEE规范与系统结构

JavaEE规范: JavaEE规范是J2EE规范的新名称,早期被称为J2EE规范,其全称是Java 2 Platform Enterprise Edition,它是由SUN公司领导、各厂家共同制定并得到广泛认可的工业标准(JCP组织成员)。之所以改名为Jav…

HTTP协议和NDS服务器

HTTP协议: HTTP的全称是:Hyper Text Transfer Protocol,意为超文本传输协议。它指的是服务器和客户端之间交互必须遵循的一问一答的规则。形容这个规则:问答机制、握手机制。它规范了请求和响应内容的类型和格式。HTTP协议是由W3C…

Servlet方法详解

Servlet: Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一。使用JavaEE的API。目前在Oracle官网中的最新版本是JavaEE8, Servlet是一个运行在web服务端的java小程序它可以用于接收和响应客户端的请求要…

继承的实现原理

一.继承的实现原理 1.继承顺序 1.1单独分叉线路&#xff1a;经典类与新式类依次从左到右&#xff0c;深度优先 1.2多条重合线路&#xff1a;经典类一路到头&#xff0c;深度优先&#xff1b;新式类&#xff0c;广度优先。<参考MRO列表&#xff0c;仅在新式类有> class A(…

Response响应方法详解

Response&#xff1a; 响应&#xff1a;服务器把请求的处理结果告知客户端。在B/S架构中&#xff0c;响应就是把结果带回浏览器。响应对象&#xff1a;在项目中用于发送响应的对象 常用状态码&#xff1a; 状态码说明200执行成功302它和307一样&#xff0c;都是用于重定向的状…

perl6 HTTP::UserAgent (2)

http://www.cnblogs.com/perl6/p/6911166.html 之前这里有个小小例子&#xff0c; 这里只要是总结一下。 HTTP::UserAgent包含了以下模块: ---------------------------------------------------------------------------------------------- Module |Path-Nam…

Java会话技术

会话技术&#xff1a; 会话指的是客户端浏览器和服务端之间的度偶次请求和响应当打开浏览器&#xff0c;访问网站地址后&#xff0c;会话开始&#xff0c;当关闭浏览器&#xff08;或者到了过期时间&#xff09;&#xff0c;会话结束。就像打电话只要不挂电话就是一次会话。 会…

【调用IP宏文件进行仿真】modelsim仿真时出现 Instantiation of 'xxx' failed. The design unit was not found....

出现错误类似&#xff1a;modelsim 仿真fifo时出现 Error: (vsim-3033) E:/Programs/ModelSim/fifo/ps2_fifo.v(75): Instantiation of scfifo failed. The design unit was not found.仿真波形不对&#xff0c;调用的ip核没有输出&#xff08;白色虚线&#xff09;等情况&…

Java Server Page

JSP JSP全称是Java Server Page&#xff0c;基于Java和Servlet一样是sun公司推出的一套开发动态web资源的技术&#xff0c;称为JSP/Servlet规范。JSP的本质其实就是一个Servlet。jsp是一种动态网页技术标准&#xff0c;jsp部署在服务器上可以处理客户端的请求&#xff0c;并根据…

HDFS概述(2)————Block块大小设置

参考&#xff1a;HDFS概述&#xff08;4&#xff09;————HDFS权限HDFS概述&#xff08;3&#xff09;————HDFS FederationHDFS概述&#xff08;2&#xff09;————Block块大小设置HDFS概述&#xff08;1&#xff09;————HDFS架构问题Q: 一个常被问到的一个问题是…

BZOJ 1083: [SCOI2005]繁忙的都市【Kruscal最小生成树裸题】

1083: [SCOI2005]繁忙的都市 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2925 Solved: 1927[Submit][Status][Discuss]Description 城市C是一个非常繁忙的大都市&#xff0c;城市中的道路十分的拥挤&#xff0c;于是市长决定对其中的道路进行改造。城市C的道 路是这样分…

Mysql介绍与安装LinuxmacOS系统

数据库&#xff1a; 用于存储和管理数据的仓库 数据库的好处&#xff1a; 可以持久化存储数据方便存储和管理数据使用了统一的方式操作数据库 – SQL 常见的数据库&#xff1a; Oracle&#xff1a;收费的大型数据库&#xff0c;Oracle公司的产品。Oracle收购SUN公司&#xff0c…

如何查看Laravel版本号的三种方法

1.PHP artisan --version 2.vim vendor/laravel/framework/src/Illuminate/Foundation/Application.php 3&#xff1a;可以写在路由里 5.4版本的路由文件夹是routes。我们可以写在routes\web.php里。 Route::get(laravel-version, function(){ $laravel app(); return…

02_反汇编_反编译

实际上安卓的应用都是zip包,只不过把zip扩展名修改了,修改成了APK.所以如果你想拿到它的图片的话,实际上特别简单&#xff0c;你就把它这个.apk换成.zip.换成.zip之后这里的图片资源就都可以拿到了. 有些公司可能美工的水平或者美工的人数比较少&#xff0c;项目还比较急&#…

SQL约束语法

约束 作用&#xff1a;对表中的数据进行限定&#xff0c;保证数据的正确性、有效性、完整性&#xff01; 约束分类&#xff1a; 约束说明PRIMARY KEY主键约束PRIMARY KEY AUTO_INCREMENT主键、自动增长UNIQUE唯一约束NOT NULL非空约束FOREIGN KEY外键约束FOREIGN KEY ON UPDAT…

修改项目名称之后,访问不到项目的问题

转载于:https://www.cnblogs.com/Joke-Jay/p/7190187.html

stanford-parser for C#

在项目里用到C#对英文句子进行词性标注。比較成熟的英文词性标注软件是stanford-parser。它个C#版本号&#xff0c;也是借助于IKVM完毕JAVA-C#的转换。详细配置过程例如以下&#xff1a; 1、下载stanford-parser的jar包 http://nlp.stanford.edu/software/lex-parser.shtml 2…

【bzoj】 1412: [ZJOI2009]狼和羊的故事

Description “狼爱上羊啊爱的疯狂&#xff0c;谁让他们真爱了一场&#xff1b;狼爱上羊啊并不荒唐&#xff0c;他们说有爱就有方向&#xff0e;&#xff0e;&#xff0e;&#xff0e;&#xff0e;&#xff0e;” Orez听到这首歌&#xff0c;心想&#xff1a;狼和羊如此和谐&am…

计算机基础--网络

互联网协议 互联网协议的功能&#xff1a;定义计算机如何接入internet&#xff0c;以及接入internet的计算机通信的标准。 互联网协议按照功能不同分为osi七层或者tcp/ip五层或tcp/ip四层 每层常见物理设备 因为学习python编程只需要了解tcp/ip五层模型&#xff0c;所以我们只需…