说到Promise大家肯定不陌生,这玩意在现在的程序里到处出现,那么我们今天就好好看一下这个东西。
Promise解决了什么问题
在代码的层面来说,提出一个东西肯定是为了解决某个问题,那么Promise是为了解决什么问题而出现的呢?
我们知道JavaScript是单线程的,但是在浏览器场景下的JavaScript是无法避免的遇到网络请求、浏览器事件这种必须异步执行的东西,所以之前大家使用事件监听调用回调的方式来执行。
但是随着项目的复杂化,可能一个回调之后会调用另一个回调,然后再调用一个回调,这样一路回调下去就会形成程序员很恶心的回调地狱。
这时候,就需要标准委员会了,在es6中规定了Promise这个东西。
Promise是什么
Promise本质上是一个绑定了回调的对象,使用方法是
function test (resolve, reject) {
resolve('success');
//当失败的时候,返回的是reject()
}
let a = Promise(test)a.then(function (result) {
console.log(result);
}).catch(function (reason) {
console.log(reason);
});
这样就是一个最简单的Promise了,这里传入的两个参数就是成功时是失败时的回调。当执行resolve的时候,Promise的状态转变为fulfilled,当执行reject的时候,状态转换为rejected。所有的rejected状态都会被catch捕捉,然后执行catch内的东西。
Promise通常都是链式调用,每个.then()后面可以再接.then(),每个.then()返回的都是Promise的话,那就可以一直的链下去。
//doSomething()是一个Promise
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
官方给出的例子可以很好的表现出来。
但是这样的东西其实还是不够清晰,一堆then在一起依旧不够简介,所以es7带来了Promise的语法糖,saync/await。
async/await
这个东西和Promise并没有任何的区别,他的存在只是因为Promise的链式调用在复杂情况下还是不够清晰。
首先,await必须在async function中出现,不能再其他的函数中出现,而await又必须操作一个Promise对象,当await操作对象不是Promise则返回操作对象本身。
await修饰的表达式会暂停async函数的执行,直到等到Promise执行完毕,若状态为fulfilled,则返回resolve作为表达式的值,然后继续执行async函数,但是如果抛出异常怎么办呢?这里没有catch接着了。
这里我们就要使用另一种方式了
async function f() {
try {
var a = await Promise.reject(30);
} catch (e) {
console.log(e); // 30
}
}
使用try/catch包裹即可,这样try里面无论是Promise抛出的异常还是其他的异常都会进入到catch中执行。
上面就是Promise的用法了,至于使用链式调用还是用es7的async/await呢?这个就看个人爱好了,我个人还是更喜欢后一种,前一种其实在直观上更符合大家的思维,后一种虽然整洁,但是需要时刻谨记await是会阻止async函数继续执行的,这点很重要。