关于ES6中的Promise——远离回调地狱

所谓“回调地狱”,相信不少用JS写异步的同学都见识过,一层又一层的函数嵌套,运行是没问题的,可是维护的时候却相当可怕。

举个最简单的例子:

function join(){
	if(true){
		function joinAgain(){
			return function item(){
				return 'done'
				}
		}
	}else{
		if(false){
			function joinSecond(){
				function joinThird(){
					function done(){
						return 'done'
					}
				}
			}
		}
	}
}

多重‘}’结尾,我们甚至很多时候如果没有IDE的提示都很难找到作用域,更别说二次维护的时候很容易出bug了,因此在代码编写中,尽可能地避免回调地狱,是非常重要的事情,所幸es6提供了Promise对象,帮助我们尽可能地回避这种困扰。

一、什么是Promise

简单来说,Promise是一个容器,里面可以用来保存某个还没开始,或将要完成的事件结果,将一些需要异步的操作放进Promise对象中,然后代码继续往下执行,当需要的时候才从Promise中获取到异步操作的结果或进行所需操作。

二、如何使用Promise

在阮一峰大神的es6文档中有个简单是示例:

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

但是我个人认为,第一次看反而不好理解,最好结合实际的例子来举例,比如说设置一个需要异步操作的函数,利用Promise来返回结果:

function timeout(ms) {
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
    	console.log('先执行我')
    	let msg = '成功后才执行我';
    	let error = '失败后才执行我'
    	let result = true
    	if(result){resolve(msg)}else{reject(error)}
    }, ms,);
  });
}

timeout(100).then(
	function(a){
		console.log(a)
	},function(b){
		consloe.log(b)
	}
);
//输出顺序:
//'先执行我'
//'成功后才执行我'

这里模拟了一个异步的操作,100毫秒之后才执行timeout函数,然后等后面所有代码执行完之后,再执行它之后的resolvereject函数(这里不知道resolvereject也没关系,后面会介绍。

三、详解Promise

还是以上面的timeout作为例子讲解:

function timeout(ms) {
  return new Promise(function(resolve, reject) {
    setTimeout(function(){
    	console.log('先执行我')
    	let msg = '成功后才执行我';
    	let error = '失败后才执行我'
    	let result = true
    	if(result){resolve(msg)}else{reject(error)}
    }, ms,);
  });
}

timeout(100).then(
	function(a){
		console.log(a)
	},function(b){
		consloe.log(b)
	}
);

关于Promise对象的结构,我们只需要了解这几点就能看明白它的运作机制:

  • Promise对象接收一个函数作为参数,如上面的:return new Promise(function(resolve, reject) {})
  • 同时,Promise里面的函数又接收两个函数作为参数,分别是resolvereject这两个函数的名字不是固定的,可以自定义,但是一般地,我们约定俗成使用resolve来代表完成后执行的方法,用reject表示出错时执行的方法。);
  • resolve表示异步成功时要做的事,它传入的参数msg会直接传到.then中,同理,reject中传入的参数error也会传到.then当中;
  • .then方法是用来指定该Promise对象成功或失败时要做的事,里面接收两个回调函数作为参数,也就是在Promise实例生成时传入的resolve方法和reject方法,但是在.then中,我们不用按原本的函数名写进去
  • .then当中,默认第一个传入的回调函数,就是代表resolve的,所以上面的function(a){}表示的就是resolve,里面的参数a也就是resolve(msg)中的msg
  • .then中的第二个函数默认代表reject,表示出错时执行的函数,也就是里面的function(b){},同理,b也就是reject(error)中的error;
  • 第二个回调函数不是必须要传的!

总结:
所以整个timeout函数实际上是个异步操作,它在100ms之后执行了第一个console,如果此时resulttrue(也就是假设异步操作成功)时,那么整个Promise实例就会被标记为resolved状态,那么在所有代码都运行完之后,它就会去.then方法中执行resolve对应的方法。

四、关于Promise的状态

从上面的总结我们知道,每个Promise实例是根据它里面的异步操作结果来标记自身状态的,然后根据不同状态再作出.then中执行resolve还是reject

Promise总的来说,有三种状态:

pending:进行中
Fulfilled:成功
rejected:失败

并且状态时不可逆的! 这就说明,如果Promise中的异步出错了,那么我们只能捕获错误并进行处理,而无法通过某些操作使它变回成功然后执行resolve方法。

五、Promise的错误处理

一般来说,我们在Promise中定义的reject(e)足以用来捕获错误,除此之外,我们还可以在用.catch()方法进行捕获,如:

promise.then((data) => {return false})
       .catch((e) => {console.log(e)}//参数e也是通过reject传递的

如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值