- 什么是
promise
- 为什么使用
promise
-
promise
用法new Promise
resolve()&rejct()
then()
-
then
链式调用 -
catch
作用 -
promise
方法Promise.all()
Promise.race()
finally()
什么是Promise
:
它是异步执行的一种解决方案。它只有三种状态:等待、成功和失败。
为什么要使用Promise
?
在执行异步操作时,往往是通过回调方式进行的。但一般来说,回调又会有好多层,例如:
操作1(function () {
// 请求成功
操作2(function () {
// 请求成功
操作3(function () {
// .......
})
})
})
在这种请求完成后再进行请求的场景下就不得不使用嵌套,这就陷入了回调地狱。
而Promise
以链式请求的形式解决了这一问题。下面我们来看一下。
Promise
用法:
不需要懂代码是什么意思,请看解释。
let p = new Promise(function (resolove, reject) {
let a = 10;
setTimeout(() => {
if (a > 0) {
resolve("Yes!");
} else {
reject("No!")
}
}, 1000)
})
p.then(function (result) {
console.log(result);//yes
}, function (result) {
console.log(result);
}
解释:
-
new Promise
创建了一个Promise
对象,并且参数是一个回调函数,回调函数中有两个参数。 -
resolve()
方法表示成功状态,将Promise
的状态由pending
(等待)变为resolve
(成功)。 -
reject()
方法表示失败状态,将Promise
的状态由pending
(等待)变为rejected
(失败)。 -
then
是Promise
的方法,也是链式调用的关键。
我们从上述代码中可以看出,异步执行不再是回调形式,而是将结果给Promise
的then
方法,即将数据从回调函数中拿出来。
new Promise
:
promist
实例可以看作是监听了请求,在请求发出后的状态是等待,进而表现为成功或者失败。而请求后所有的操作放在了then
方法里。因为在promise
中只是让我们知道了它的状态是等待成功或者失败,并没有进行操作。
resolve()
&reject()
:
对于这两个方法是用来改变promise
状态的,并且状态一旦改变就不能被更改。比如在执行完resolve()
方法后状态变为resolved
,那这个对象的最终状态就是这个。
then
:
then
充当回调,并接收两个函数,第一个函数始终表示为成功状态,第二个函数始终表示为失败状态。并且参数result
表示结果,是由resolve()
或reject()
传进来的。
但问题又来了,我们想要进行多个请求时怎么写?
let p = new Promise(function (resolve, reject) {
let a = 10;
setTimeout(() => {
if (a > 0) {
resolve("Yes!");
let b = 10;
setTimeout(() => {
//.....
}, 1000)
} else {
reject("No!")
}
}, 1000)
})
p.then(function (result) {
console.log(result);//yes
}, function (result) {
console.log(result);
}
这么写吗?在第一次状态为成功态时,请求第二次?那这样不就再次陷入回调地狱了吗?
then
链式调用:
上文我们已经提过,then
可以接收两个函数,当然我们还可以再每一个then
中创建新的promise
然后将这个promise
返回,再交给then
处理。
let p = new Promise(function (resolve, reject) {
let a = 10;
setTimeout(() => {
if (a > 0) {
resolve("Yes!");
} else {
reject("No!")
}
}, 1000)
}
p.then(function (result) {
console.log(result);//yes
return p = new Promise(functio(resolve,reject) {
let b = -10;
setTimeout(() => {
if (b > 0) {
resolve("Yes!");
} else {
reject("No!");
}
})
})
}, function (result) {
console.log(result);
})
.then(function (result) {
console.log(result);
}, function (result) {
console.log(result); // No!
})
就像这样,在第一次请求完毕返回一个新的promise
。这样写虽然比较乱,但解决了回调地狱问题。在第一次请求完毕后,创建新的对象并返回。然后给then
处理,所以就形成了then
的链式调用。
then
链式调用美化
function r1() {
return new Promise(function (resolve, reject) {
let a = 10;
setTimeout(() => {
if (a > 0) {
resolve("Yes!");
} else {
reject("No!")
}
}, 1000)
})
}
function r2() {
return new Promise(function (resolve, reject) {
let b = -10;
setTimeout(() => {
if (b > 0) {
resolve("Yes!");
} else {
reject("No!");
}
})
})
}
let p = r1();
p.then(function (result) {
console.log(result);//yes
return r2();
}, function (result) {
console.log(result);
}).then(function (result) {
console.log(result);
}, function (result) {
console.log(result); //No
})
既然我们已经明白怎样进行链式调用,那上方代码就是美化都的结果。将请求抽离封装,返回一个状态。并在then
方法中链式调用。
虽然会失败,但程序不会停止执行。
catch()
:
catch()
其实也是处理reject()
。处理报错时使用的try-catch
语句和这里的catch()
差不多。
既然reject()
表示失败状态,并且我想要的结果是在前一个请求成功的基础上再进行下一次请求,那我直接将错误收集起来,如果有一个报错,就停止执行。
function r1() {
return new Promise(function (resolve, reject) {
let a = 10;
setTimeout(() => {
if (a > 0) {
resolve("Yes!");
} else {
reject("No!")
}
}, 1000)
})
}
function r2() {
return new Promise(function (resolve, reject) {
let b = -10;
setTimeout(() => {
if (b > 0) {
resolve("Yes!");
} else {
reject("No!");
}
})
})
}
let p = r1();
p.
then(function (result) {
console.log(result);//yes
return r2();
}).
then(function (result) {
console.log(result);
return r1();
}).
then(function (result) {
console.log(result);
})
.catch(function (result) {
console.log(result);//no
在第二次请求失败后就会结束执行。
Promise
方法:
Promise.all()
:同时监听多个请求,并参数是数组,数组中每一项都是promise
实例。若每一项都是成功状态,这个新的promise
才会成功,否则失败状态。
//r1、r2在上面代码中已经定义。
let p = Promise.all([r1(), r2()]);
p.then(function (result) {
console.log(result)
}).catch(function (result) {
console.log(result) //No
})
Promise.race()
:同时发送多个请求 但是它是跟随最早发生变化的那个Promise。假设最先改变的是r2变成rejected
状态,那返回的就是失败状态。
//r1、r2在上面代码中已经定义。
let p = Promise.race([r1(), r2()]);
p.then(function (result) {
console.log(result)
}).catch(function (result) {
console.log(result)
})