先抛出一个问题:
问:js为什么不设计为多线程的语言呢?
答: 因为js是可以操作DOM的,如果js设计为多线程的语言,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时候浏览器该以哪个线程为准呢?
为了利用多喝CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个县城,但是子线程完全受主线程控制,且不得操作DOM,所以新表真并没有改变js单线程的本质。
很多时候,我们在加载图片或接口时候,接口的耗时难免会造成页面的阻塞,因此就要考虑到异步加载了,这个时候就会想到promise。
1、es6中的promise
Promise对象存在 Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)三种状态。
let p = new Promise((resolve, reject) => {
//做一些异步操作
if (/* 异步操作成功 */){
resolve(data);
} else {
reject(err);
}
});
上面的代码是Promise的构造函数,可以看到此构造函数接收一个参数:函数,并且这个函数需要传入两个参数:
(1)resolve:异步操作执行成功后的回调函数,将Promise对象的状态从‘未完成’变为‘成功’(pending变为resolved)
(2)reject:异步操作执行失败后的回调函数,将Promise对象的状态从‘未完成’变为‘失败’(pending变为rejected)
2、Promise的使用
Promise自己身上本身有all、reject、resolve等方法,原型上有then、catch方法。
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num); //状态为resolve
}
else{
reject('数字太大了'); //状态为reject
}
}, 2000);
});
p.then((data) => {
console.log('resolved',data);
},(err) => {
console.log('rejected',err);
}
);
- then的使用
当函数中的异步操作设置了resolve及reject状态的回调后,这样我们在函数调用时,then中就可以捕捉到。then接收两个参数,第一个应对resolve的回调,第二个对应reject的回调,这样我们可以分别拿到传过来的数据。 - catch的使用
Promise的catch方法,其实和then的第二个参数一样,用来指定reject的回调。使用时直接在then后面链式拼接使用就好。
p.then((data) => {
console.log('resolved', data);
}).catch((err) => {
console.log('reject', err)
});
虽然和then的第二个参数效果一样,但是他还有另一个作用,在执行resolve的回调时,,如果跑出异常了(代码报错了),那么并不会报错卡死js,而是会进入到这个catch方法中。这与try/catch语句的作用相同。
- Promise的all方法
all方法提供了并行执行异步操作的能力,并且在左右的异步操作执行完毕后才执行回调。
all接收一个数组参数,里面的值最终都返回Promise对象
let Promise1 = new Promise(function(resolve, reject){ resolve('11111'); })
let Promise2 = new Promise(function(resolve, reject){ resolve('22222'); })
let Promise3 = new Promise(function(resolve, reject){ resolve('33333'); })
let p = Promise.all([Promise1, Promise2, Promise3])
p.then((data) => {
// 三个都成功则成功
console.log(data); // ['11111', '22222', '33333'] 返回所有的数据
}, (err) => {
// 只要有失败,则失败
})
使用all,就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据。
3、promise的作用:
解决回调地域(回调嵌套很多),代码难以维护,常常第一个函数的输出是第二个函数的输入的现象;
- promise可以支持多个并发的请求,获取并发请求的数据;
- promise可以解决异步的问题,本身不能说promise是异步的。
*** 参考链接:Promise不会??看这里!!!史上最通俗易懂的Promise!!!
*** 更详细的讲解请见阮一峰老师的Promise对象,里面有‘异步加载图片’及‘用Promise对象实现的 Ajax 操作’的例子。