背景
javascript是基于单线程事件循环的概念构建的,同一时刻只允许一个代码块执行。
js引擎同一时刻只能执一个代码块,所以需要跟踪即将运行的代码。代码被放到一个任务队列中,每当一段代码准备执行时,都会被添加到任务队列中。当一段代码结束执行,事件循环会执行队列中的下一个任务。
然而,浏览器的网络请求和事件都是异步执行的。ajax是典型的异步操作。如下jquery代码:
$.ajax({
data: data,
url: url,
success: function() {
// code...
},
error: function() {
// code..
}
})
有没有更好的写法呢? 比如:
ajaxGet('http://...')
.ifSuccess(success)
.ifFail(fail);
这样就把执行代码和处理结果的代码分开处理。
ES6提供了promise来处理异步执行,把执行代码和处理结果的代码清晰地分离了。当执行若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数.
job1.then(job2)
.then(job3)
.catch(handleError);
Promise的基本用法:
生命周期
每个promise都会经历一个生命周期:未完成(pending)和已完成。已完成的状态又分两种情况:操作成功(resolved)和操作失败(rejected)。
创建promise
- 创建未完成的promise
new Promise(function(resolve, reject) {})
- 创建操作成功的promise
new Promise(function(resolve, reject) {
resolve()
})
- 创建操作失败的promise
new Promise(function(resolve, reject) {
reject()
})
所有的Promise都有then()方法,接收两个参数:操作成功的处理函数和操作失败的处理函数。只有当Promise的状态改变时,才会通过then()方法采取特定的操作。
new Promise(function(resolve, reject) {
resolve(42)
}).then(function(value) {
alert(value)
}, function(value) {
alert('err')
});
new Promise(function(resolve, reject) {
reject(42)
}).then(function(value) {
alert(value)
}, function(value) {
alert('err')
});
通常,我们都采用链式调用的写法
new Promise(function(resolve, reject) {
resolve(42);
}).then(function(value) {
alert(value);
}).catch(function() {
alert('err');
})
new Promise(function(resolve, reject) {
reject(42);
}).then(function(value) {
alert(value);
}).catch(function() {
alert('err');
})
串联promise
Promise调用then()或catch()方法后都会返回一个操作成功状态的promise,这让我们可以继续对返回的promise进行处理。
在完成处理程序中指定一个返回值,则可以沿着这条链继续传递数据。
new Promise(function(resolve, reject) {
reject(42)
}).catch(function(value) {
console.log(value)
return value+1
}).then(function(value) {
console.log(value)
return value+1
});
promise中返回promise
promise只要创建就必须被捕获,否则浏览器会报错
var p1 = new Promise(function(resolve, reject) {
reject('reject1')
});
var p2 = new Promise(function(resolve, reject) {
resolve('resolve1')
})
new Promise(function(resolve, reject) {
reject(60)
}).then(function(value) {
console.log(value)
return p2
}).catch(function(value) {
console.log(value)
return p1
}).then(function(value) {
console.log(value)
}).catch(function(value) {
console.log(value)
})
响应多个promise(具体内容请大家自学)
promise提供了all()和race()来响应多个promise。
all()方法当所有的Promise都被解决后返回的Promise才会被解决,只要有一个Promise被拒绝返回的Promise就会被拒绝。
race()方法中传入的Promise会进行竞选,一旦来源Promise中有一个被解决,不管是resolve还是reject,所返回的 Promise 就会立刻被解决。
Promise的异步任务执行
我们在项目中使用axios来请求处理数据。axios就实现promise的异步请求。类似结构如下
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});