要了解Promise 就要首先了解同步和异步的概念:
JavaScript是单线程语言,在执行任务的时候,会先执行第一个任务再执行第二个任务,假如第一个任务是个耗时的任务那么第二个任务就一直阻塞不能执行,那么这个时候就需要异步来处理这个操作;
同步:主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务;
异步:不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程;
最常用的异步操作就是将回调函数作为异步回调的参数来使用,而promise是通过then来做的;
new promise 的时候就会被立即执行,因而为了实现用的时候调用所以将promise写在函数里面;
常见的异步操作代码:
function ee (callBack) {
setTimeout( ()=> {
callBack()
console.log('这是第3个被执行的')
},0)
console.log('这是第1个被执行的') // 异步
}
ee( ()=>{
console.log('这是第2个被执行的')
})
// 这是第1个被执行的
// 这是第2个被执行的
// 这是第3个被执行的
Promise:
是一种异步编程的解决方案,有三种状态,pending(进行中)、resolved(已完成)、rejected(已失败),特点是只有异步操作的结果,可以决定当前是哪一种状态,状态一旦改变,就无法再次改变状态;
简单地说,Promise好比容器,里面存放着一些未来才会执行完毕(异步)的事件的结果,而这些结果一旦生成是无法改变的
Promise的作用:
1,主要是用来解决回调嵌套(执行完后再去执行某一些操作,这时候容易形成嵌套再嵌套的问题)的问题,也就是常见的"回调地狱"; 2,执行多并发请求获取数据;
Promise的使用:
1,创建 Promise 实例,var pr = new Promise();
2,实例创建以后可以用 .then 方法来指定 resolved状态 和 reject状态 的回调函数;
3,用常见的两种异常机制来捕获异常;
Promise常用的方法:
1,类方法(静态方法):
resolved:成功状态返回一个 Promise 对象;
reject:失败状态返回一个Promise 对象;
race:多个 Promise 任务同时执行,返回最先执行结束的 Promise 任务的结果,不管这个 Promise 结果是成功还是失败;
all:如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果,如果有错误就返回reject的结果;
2,实例方法:
.then:为 Promise 注册回调函数,函数一定要 return 一个结果或者一个新的 Promise 对象,才可以让之后的then 回调接收;
.catch:异常处理;
let Promise1 = new Promise(function(resolve, reject){})
let Promise2 = new Promise(function(resolve, reject){})
let Promise3 = new Promise(function(resolve, reject){})
let p = Promise.all([Promise1, Promise2, Promise3])
p.then(funciton(){
// 三个都成功则成功
}, function(){
// 只要有失败,则失败
})
//请求某个图片资源
function requestImg(){
var p = new Promise((resolve, reject) => {
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = '图片的路径';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise.race([requestImg(), timeout()]).then((data) =>{
console.log(data);
}).catch((err) => {
console.log(err);
});
Promise的执行过程是怎么样的?
先new了一个实例,然后立即执行他后面的function,这个function是同步执行的,然后再去用实例去"注册".then方法,为什么叫注册,因为他并没有执行,之后去执行没有执行完的那些同步代码,同步执行完后才去时间循环中检测是否有可用的Promise回调,如果有就执行,没有就不执行;
补充知识点"事件循环":
程序最开始就是按照顺序执行,遇到同步直接执行,遇到异步,先用异步函数发起异步请求,此时,异步任务开始执行异步操作,操作完了以后放在消息队列中进行排队,等代码按顺序执行完了以后才去队列里面看是否还有没执行的消息,如果有,将消息按照顺序拿出来放到栈中去执行,执行完再看有没有,一直反复直到结束;
主线程从"任务队列"中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。此机制具体如下:主 线程会不断从任务队列中按顺序取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个 任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去 任务队列中取下一个任务执行。
Promise还有哪些问题?
promise一旦执行,无法中途取消
promise的错误无法在外部被捕捉到,只能在内部进行预判处理
promise的内如何执行,监测起来很难
解决办法:
正是因为这些原因,ES7引入了更加灵活多变的async,await来处理异步
Promise两种异常处理的不同:
1,直接为失败的Promise指定回调函数;这个异常的特点是捕获异常,哪怕前面的Promise执行失败了,也可以执行后面的.then操作,对后面的Promise没有影响;
2,通过 .catch() 的方式捕获异常,这样的特点是前面只要有一个Promise出现异常就会立即终止,并捕获这个异常;
代码解析:
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务1执行完成');
resolve('随便什么数据1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务2执行完成');
resolve('随便什么数据2');
}, 1000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务3执行完成');
resolve('随便什么数据3');
}, 1000);
});
return p;
}
runAsync1().then(function(data){
console.log(data);
return runAsync2();
}).then(function(data){
console.log(data);
return runAsync3();
}).then(function(data){
console.log(data);
});
// 异步任务1执行完成
// 随便什么数据1
// 异步任务2执行完成
// 随便什么数据2
// 异步任务3执行完成
// 随便什么数据3