es6新特性之Promise

你可能见到过这样的代码:

 $.ajax({
		url:"xServlet"
	}).done(function (xret){
		console.log(xret);
		$.ajax({
			url:"y1Servlet",
			data:xret,
			success:function(y1ret){
				console.log(y1ret);
			}
		});
		$.ajax({
			url:"y2Servlet",
			data:xret,
			success:function(y2ret){
				console.log(y2ret);
			}
		});
	}).fail(function(xret){
		console.log(xret);
	});

执行结果:

image.png

意思是,请求地址y1Servlet和y2Servlet依赖请求地址xServlet的执行,这时候我们只能使用这种嵌套的方式才能确保正确的ajax执行顺序,上面的代码我仅仅只是为了演示,真实的情况可能远比上面的代码复杂,因为真实的情况可能还要处理很多的东西,嵌套的层数也可能会更多,对于这种不便于阅读、不便于维护的嵌套,大家都“亲切地”称之为“嵌套地狱”,可想而知,它的可怕性。

es6中为了解决这种嵌套的问题,推出了Promise这个类,怎么使用呢?那我就先使用Promise把上面的类改写一番,大家比较一下可阅读性:

<script>
	function ajaxRequest(reqesturl,requestdata){
		  let dtd=$.Deferred();
		  $.ajax({
		         url: reqesturl,
		         data: requestdata
		    }).done(function(result){
				dtd.resolve(result);
		    }).fail(function(err){
				dtd.reject();
		    });
		    return dtd.promise();
	}
	var px=new Promise(function(resolve,reject){
		ajaxRequest("xServlet").done(function (xret){
			resolve(xret);
		}).fail(function(xret,textStatus){
		        reject(xret);
			console.log(textStatus);
		});
	});
	//Promise对象(这里一px为例)的then有两个参数,then(f1,f2),当px的状态为成功(执行了resolve(xx))的时候进入
	//f1,当px的状态为成功(执行了reject(xx))的时候进入f2
	var py1=px.then(function(successMsg){
		console.log("px这个Promise对象状态为成功的时候进入");
		console.log(successMsg);
	 	return new Promise(function(resolve,reject){
	 		ajaxRequest("y1Servlet",successMsg).done(function (y1ret){
				resolve(y1ret);
			});
	 	}); 
	},function(errorMsg){
		console.log("px这个Promise对象状态为失败的时候进入");
	});
	
	var py2=px.then(function(successMsg){
	 	return new Promise(function(resolve,reject){
	 		ajaxRequest("y2Servlet",successMsg).done(function (y2ret){
				resolve(y2ret);
			});
	 	}); 
	}).catch(function (errorMsg){//相当于then的第二个参数
		console.log("px这个Promise对象状态为失败的时候进入");
		console.log(errorMsg);
	});
	
	Promise.all([px,py1,py2]).then(function(arr){
		console.log("px,py1,py2这3个Promise对象状态都为成功的时候进入");
		console.log(arr)
	});
</script>

先贴上执行结果:

image.png

你看了肯定会吃惊,我擦,几行代码让你改写一下翻了一倍了,这么麻烦,我用它干什么?我为了尽可能的把Promise对象讲解清楚,把它的方法都用上,写了很多冗余的代码,才导致你看起来代码很多,其实代码的多少不耽误你的阅读速率,关键在于是否具有很强的可读性。

你看到上面的代码,可能就像是看天书,完全不知道哪跟哪,那么该如何理解上面的代码呢?

从上往下看:

1.先看ajaxRequest这个函数,这里用到了jQuery的deferred对象,可以参考“jquery里面的deferred对象”这篇教程。

2.创建一个Promise对象的格式:var promise1=new  Promise(function(resolve,reject){});其中参数resolve和reject本质是一个函数,因此你才可以看到下面的函数调用方式-------resolve(xret)以及reject(xret),  那么调用resolve函数和reject函数有什么用呢?

3.调用resolve函数和reject函数的作用分别是修改对应的Promise对象(这里假设对象名字叫做promise1)promise1的状态为Fulfilled和Rejected,Promise的实例对象有三种状态:

            Fulfilled :成功

            Rejected  :失败

            pending:刚初始化

也就是说,resolve(xret)会修改promise1的状态为成功,reject(xret)会修改promise1的状态为失败。

4.程序继续往下走,到了promise1.then这个方法,then有两个参数,then(f1,f2),当px的状态为成功(执行了resolve(xx))的时候进入f1,当px的状态为成功(执行了reject(xx))的时候进入f2。f1和f2的参数就是执行resolve(xret)或reject(xret)时传入的参数xret。then 可以使用链式调用,每一次执行then时总是会返回一个 Promise 对象。另外,在 then onFulfilled 的函数当中的返回值,可以作为后续操作的参数。

f1().then(function (msg) {
    return msg;
}).then(function (msg) {
    return msg  + ' 1';
}).then(function (msg) {
    return msg + '2';
}).then(function (msg) {
    alert(msg);
});

5.catch的作用和then的第二个参数f2的作用一样,都是当promise1的状态为失败的时候去执行。catch 方法是 then(onFulfilled, onRejected) 方法当中 onRejected 函数的一个简单的写法,也就是说可以写成 then(fn).catch(fn),相当于 then(fn).then(null, fn)

6.Promise.all(Promise实例的数组a).then(function(arr){})的作用是当a里面的所有Promise实例的状态都为成功的时候才去执行后边的then,这里then的参数arr就是数组a,你可以在这里编写自己的逻辑。

另外,还有个Promise.race,它同样接收一个数组,跟Promise.all的格式是完全一样的,不同的是只要该数组中的 Promise 对象的状态有一个发生变化(无论是 resolve(即成功) 还是 reject(即失败))该race方法都会执行后边的then。

附录:

xServlet:

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 
	IOException {
		 response.setContentType("application/json; charset=utf-8");
		 PrintWriter out = response.getWriter();
		 List<String> xList=new ArrayList<String>();
		 xList.add("2018-03-20");
		 xList.add("2018-03-21");
		 xList.add("2018-03-22");
		 JSONArray jsonArray=JSONArray.fromObject(xList);
		 out.println(jsonArray);
	}

y1Servlet:

 response.setContentType("application/json; charset=utf-8");
		 PrintWriter out = response.getWriter();
		Map<String, Object> retMap=new HashMap<String, Object>();
		retMap.put("2018-03-20", "33");
		retMap.put("2018-03-21", "44");
		retMap.put("2018-03-22", "55");
		 JSONObject jsonObject=JSONObject.fromObject(retMap);
		 out.println(jsonObject);

y2Servlet:

response.setContentType("application/json; charset=utf-8");
		 PrintWriter out = response.getWriter();
			Map<String, Object> retMap=new HashMap<String, Object>();
			retMap.put("2018-03-20", "赵云");
			retMap.put("2018-03-21", "阿珂");
			retMap.put("2018-03-22", "武则天");
			JSONObject jsonObject=JSONObject.fromObject(retMap);
			out.println(jsonObject);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值