使用背景
这里只讲promise的如何使用,适用于什么情况下。不手撕源码,想看手撕源码请移步B站搜索promise。
假设我们现在有一串代码,用来判断现在输入的字符换是不是“abcd”。这段代码比较傻,只会一个字符换一个字符串的判断。
function check(str){
if (str[0]=='a'){
if (str[1]=='b'){
if (str[2]=='c'){
if (str[3]=='d'){
if (str[4]== undefined ){
console.log("这个字符串就是abcd")
}
else{
console.log("该字符串不是abcd")
}
}
else{
console.log("该字符串不是abcd")
}
}
else{
console.log("该字符串不是abcd")
}
}
else{
console.log("该字符串不是abcd")
}
}
else{
console.log("该字符串不是abcd")
}
}
这里可以看到,这里有很多if,else嵌套。因为只是判断字符所以代码看起来还是比较规律的。这是同步的程序,如果是异步的还带有回调函数的代码,代码的可读性就不是那么高了。
promise初探
promise对象有三种状态分别是
- pending
- resolved(fulfilled)
- rejected
我们可以使用var 对象名 = new Promise(function(resolve,rejected)) 的方式生成promise对象。function(resolve,rejected)称为执行函数
生成对象的过程中,如果一直不使用resolve或者reject函数来设置promise的状态,那么promise对象将一直为pending状态。
var temp = new Promise(function(resolve,reject) {
})
console.log(temp)
//[[PromiseStatus]]: "pending"
//[[PromiseValue]]: undefined
如果使用resolve函数,那么promise对象就变成了fulfilled状态了。
var temp = new Promise(function(resolve,reject) {
resolve('调用了resolve函数')
})
console.log(temp)
//[[PromiseStatus]]: "fulfilled"
//[[PromiseValue]]: "调用了resolve函数
同理使用了reject函数,promise对象就变成了rejected状态
var temp = new Promise(function(resolve,reject) {
reject('调用了reject函数')
})
console.log(temp)
//[[PromiseStatus]]: "rejected"
//[[PromiseValue]]: "调用了reject函数"
then()函数
then函数的用法:promise对象.then(fulfilled状态对应的函数,rejected状态对应的函数)
百度抄的定义:第一个then不管是走成功还是失败的回到函数,只要返回一个普通值(不抛出错误或者返回promise),都会执行下一个then的成功的回调。---------------------我的理解是,不使用throw抛出错误或者返回一个promise对象,下一个then就调用resolve对应的函数,反之调用rejecte对应的函数。
当peomise对象是fulfilled状态,就会调用fulfilled状态对应的函数。
同理当peomise对象是rejected状态,就会调用rejected状态对应的函数。
总结:
使用resolve对应函数的两种情况1、promise对象为resolved状态且第一次调用then 2、前一个then返回的不是promise对象或抛出错误。
使用resolve对应函数的两种情况1、promise对象为rejected状态且第一次调用then 2、前一个then返回的是promise对象或抛出错误。
var temp = new Promise(function(resolve,reject) {
resolve('调用了resolve函数')//这里使用了resolve所以promise就变成了fulfilled
})
temp
.then(
function(data) {
console.log(data) //输出为 “调用了resolve函数” 时第二行调用resolve函数的时候将值放入PromiseValue中了
console.log('promise调用了resolve函数')//该行输出
},
function(data) {//该函数不执行,因为promise对象不是rejeted状态
console.log(data)
console.log('promise调用了reject函数')
}
)
当peomise的状态时pending的时候,then函数不会执行。
var temp = new Promise(function(resolve,reject) {
// resolve('调用了resolve函数')
})
a = temp
.then(
function(data) {//该函数不执行
console.log(data)
console.log('promise调用了resolve函数')
},
function(data) {//该函数不执行
console.log(data)
console.log('promise调用了reject函数')
}
)
且个人建议使用then的时候返回对象为promise对象,这样比较清晰,不然在后面使用settimeout可能会有些出乎意料的问题。
var temp = new Promise(function(resolve,reject) {
console.log('第0层')
resolve()
})
a = temp
.then(
function() {//该函数被调用因为使用了resolve函数,promise对象是fulfilled
console.log()
console.log('第1层的resolved对应的函数')
return new Promise(function(resolve,reject) {reject('')})
},
function() {//该函数不会被调用
console.log()
console.log('第1层的rejected对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
}
)
.then(
function() {//该函数不会被调用
console.log()
console.log('第2层的resolved对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
},
function() {//该函数会被调用
console.log()
console.log('第2层的rejected对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
}
)
//输出为:
//第0层
//第1层的resolved对应的函数
//第2层的rejected对应的函数
这里要注意第一个then调用的是resolve对应的函数,因为一开始的peomise对象被设置成fulfilled状态了。第二个then调用的是rejected对应的函数,因为再第一个then返回的peomise对象的状态是rejected的
catch()函数
在then()函数中可以省略rejected状态对应的函数,例如在then的链式调用中只要出现异常就推出。这个时候由catch来捕获rejected状态并且对其做出反应。
var temp = new Promise(function(resolve,reject) {
console.log('第0层')
resolve()
})
a = temp
.then(
function() {
console.log()
console.log('第1层的resolved对应的函数')
return new Promise(function(resolve,reject) {reject('')})
},
)
.then(
function() {
console.log()
console.log('第2层的resolved对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
},
)
.catch(function() {
console.log("错误 我抓住你了")
})
//输出为:
//第0层
//第1层的resolved对应的函数
//错误 我抓住你了
这里第一个then返回的promise对象的状态是rejected的,应该调用第二个then对应的rejected状态对应的函数,可是第二个then没有rejected对应的函数,那么就会接着向下找,就找到了catch()。然后执行catch函数体。这也称为catch的穿透性。
接着我们看下面这串代码
var temp = new Promise(function(resolve,reject) {
console.log('第0层')
reject()
})
a = temp
.then(
function() {
console.log()
console.log('第1层的resolved对应的函数')
return new Promise(function(resolve,reject) {reject('')})
},
)
.then(
function() {
console.log()
console.log('第2层的resolved对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
},
function() {
console.log()
console.log('第2层的rejected对应的函数')
return new Promise(function(resolve,reject) {resolve('')})
}
)
.catch(function(params) {
console.log("错误 我抓住你了")
})
//输出为:
//第0层
//第2层的rejected对应的函数
我们在第0层的时候就将promise对象的状态设置为rejected了,那么应该执行第一个then的rejected函数。可是第一个then没有,再找第二个then。第二个then有rejected对应的函数,就执行第二个rejected对应的函数,但是不执行catch。因为这个时候穿透不到catch
all()函数
列表中的所有promise对象都从pending转换成resolved后,all执行结束。第一个promise对象失败,返回这个失败的对象。
function resolveTest(content) {
return new Promise(function (resolve, reject) {
resolve(content)
})
}
function rejectTest(content) {
return new Promise(function (resolve, reject) {
reject(content)
})
}
var resolveTestPromise = Promise.all([resolveTest(1),resolveTest(2),resolveTest(3)])
var rejectTestPromise = Promise.all([resolveTest(1),rejectTest(2),rejectTest(3)])
console.log(resolveTestPromise)
//输出为:
//[[PromiseStatus]]: "fulfilled"
//[[PromiseValue]]: Array(3)
console.log(rejectTestPromise)
//输出为:
//[[PromiseStatus]]: "rejected"
//[[PromiseValue]]: 2
all方法适合使用在需要多个异步返回的结果的情况下
race()函数
哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
function resolveTest(content) {
return new Promise(function (resolve, reject) {
resolve(content)
})
}
function rejectTest(content) {
return new Promise(function (resolve, reject) {
reject(content)
})
}
var testPromise = Promise.all([rejectTest(1),resolveTest(2),resolveTest(3)])
console.log(testPromise)
//输出为:
//[[PromiseStatus]]: "rejected"
//[[PromiseValue]]: 1
Promise.reject()函数
返回一个带有拒绝原因的Promise对象。
var rejectPromise = Promise.reject("这是一个rejectd的promise对象")
console.log(rejectPromise)
//输出为:
//[[PromiseStatus]]: "rejected"
//[[PromiseValue]]: "这是一个rejectd的promise对象"
Promise.resolve()函数
用法1
返回一个带有拒绝原因的Promise对象。
var rejectPromise = Promise.reject("这是一个rejectd的promise对象")
console.log(rejectPromise)
//输出为:
//[[PromiseStatus]]: "rejected"
//[[PromiseValue]]: "这是一个resolve的promise对象"
用法2
传入一个带有then方法的对象,会立即执行这个方法。
var objwiththen = {
then: function(resolve, reject) {
resolve(42);
}
};
var p1 = Promise.resolve(objwiththen);
console.log(p1)
//输出:
//[[PromiseStatus]]: "fulfilled"
//[[PromiseValue]]: 42