JavaSccript异步Promise.then()与Promise.catch()

我们先打印Promise原型下都带有哪些方法

console.log(Promise.prototype)

输出:
JavaSccript异步Promise.then()与Promise.catch()_第1张图片

Promise.then()

语法

p.then(onFulfilled,onRejected)
p.then(function(value) {
  // fulfillment
 }, function(reason) {
   // rejection
});

参数

onFulfilled
当Promise变成接受状态(fulfillment)时,该参数作为回调函数被调用(参考: Function)。该函数有一个参数,即接受的最终结果(the fulfillment value)。如果传入的 onFulfilled 参数类型不是函数,则会在内部被替换为(x) => x ,即原样返回 promise 最终结果的函数
onRejected (可选)
当Promise变成拒绝状态(rejection )时,该参数作为回调函数被调用(参考: Function)。该函数有一个参数,,即拒绝的原因(the rejection reason)。

直接上代码:

let promise = new Promise((resolve,reject) =>{
resolve("成功了!");
// reject("出错了!")
}))
promise.then(
function(value){
console.log(value)
},
function(reason){
console.log(reason)
}
)

输出:

成功了!
// 出错了!
then 方法返回一个Promise 对象,其允许方法链。 下面我们继续看例子:
Promise.reject('出错了')
    .then(res => console.log(`res1:${res}`), err => console.log(`err1:${err}`))
    .then(res => console.log(`res2:${res}`), err => console.log(`err2:${err}`));

输出:

// err1:出错啦
// res2:undefined

分析

上面代码中的Promise.reject(‘出错了’)还可以这么写:

Promise.reject('出错了')
  等价于
new Promise(reject =>{
  reject('出错了')
})
resolve和reject当传入一个字符串作为参数时,则会返回一个新的Promise实例

如果是resolve,新的Promise对象的状态为resolve
如果是reject,新的Promise对象的状态为reject
上面的两种写法都会返回一个新的Promise实例,并且状态为reject

Promise.reject('出错了')
    .then(res => { 
    console.log(`res1:${res}`)  // 这里不执行
    }, err => {
    console.log(`err1:${err}`) //  err1:出错了!
    })
    // 最后输出 : err1:出错了!

Promise状态为reject,所以执行了then下面第二个参数的方法;
我们前面说过then()的第二个参数可不选,我们继续往下看:

Promise.reject('出错了')
    .then(res => { 
    console.log(`res1:${res}`)  // 这里不执行
    })

输出:
JavaSccript异步Promise.then()与Promise.catch()_第2张图片
我们发现报了个未知的错误,当我们省略了第二个参数之后那么,catch()就非常有意义了,讲catch之前我们再看下then()的返回值

返回值

then方法返回一个Promise,而它的行为与then中的回调函数的返回值有关:
直接上代码:

const promise = new Promise(reject =>{
    reject("出错了!")
})
// 第一个 then()
.then(res =>{
console.log(`res1:${res}`) // 这里不执行
return 1
},err =>{
console.log(`err1:${err}`) // err1:出错了!
})
// 第二个 then()
.then(res =>{
console.log(`res2:${res}`) // 1
throw "这是一个错误提示!"
},err =>{
console.log(`err2:${err}`) // 这里不执行
})
// 第三个 then()
.then(res =>{
console.log(`res3:${res}`) // 这里不执行
},err =>{
console.log(`err3:${err}`) // 这是一个错误提示!
})
// 第四个 then()
.then(res =>{
console.log(`res4:${res}`) // undefined
},err =>{
console.log(`err4:${err}`) // 这里不执行
})
// 第五个 then()
.then(res =>{
console.log(`res5:${res}`) // undefined
},err =>{
console.log(`err5:${err}`) // 这里不执行
})

输出:
JavaSccript异步Promise.then()与Promise.catch()_第3张图片
关于MDN上返回值的介绍,解释的有点绕:

  如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。
我们看完返回值的介绍之后,再来分析下promise:
  promise直接执行的reject(‘出错啦’),返回的是一个promise对象,状态为reject ,所以第一个then执行的第二个参数方法,输出: res:出错了,然后return 1
  我们看第二个then的输出,可以发现,第一个then的return值会作为下第二个then的回调函数的参数值,第二个then又执行了throw
  第二个then的throw,使得第三个then下的Promise对象状态为reject,
  所以第三个then输出: err3:这是一个错误提示! ,第三个then没有返回值,也没有执行throw ,
  所以第四个then输出: res4:undefined
  第四个then和第三个then一样,没有返回值,所以第五个then输出的结果和第四个一样输出: res4:undefined

我们做一下总结:
如果前一个Promise对象是resolve状态,则后一个Promise对象执行第一个参数方法(resolve)
如果前一个Promise对象是reject状态,则后一个Promise对象执行第二个参数方法(reject)
如果前一个Promise对象抛出一个自定义的异常(throw),则后一个Promise对象执行第二个参数方法(reject)
如果前一个Promise对象返回具体的值,则此数值将作为后一个Promise对象的输入,执行第一个参数方法(resolve)
如果前一个Promise对象没有返回状态(resolve或者reject),也没有抛错(throw),也没有返回具体数值,我们则认为它返回 了一个undefined,则undefined将作为后一个Promise对象的输入,执行第一个参数方法(resolve)
我们再回头看下我们前面的一个例子:

Promise.reject('出错啦')
    .then(res => console.log(`res1:${res}`), err => console.log(`err1:${err}`))
    .then(res => console.log(`res2:${res}`), err => console.log(`err2:${err}`));

现在看来就好理解了 因为前面是reject状态,所以第一个then执行第二个参数方法 “err => console.log(err1:${err})”

因为第一个then方法,没有返回状态,没有抛错,没有返会具体值,所以返回的是undefined,第二个then执行 “res => console.log(res2:${res}”

Promise.catch()

其实then方法懂了,catch自然也就明白了,因为,catch()就类似于.then(null, rejection)或.then(undefined, rejection)
catch用于捕获错误,它的参数也就是then的第二个参数
我们将上面的代码做一下改动

const promise = new Promise((resolve, reject) => {
    reject('出错了');
})
.catch(err => {
    console.log(`catch1:${err}`) // catch1:出错了
    return 1;
})
.then(res => {
    console.log(`then1:${res}`) // then1:1
    throw "这是一个错误提示!"
})
.catch(err => {
    console.log(`catch2:${err}`) // catch2:这是一个错误提示
})
.then(res => {
    console.log(`then2:${res}`) // then2:undefined
})

如果上面的关于then的介绍看懂了,这个自然就会明白
关于promise的then和catch就介绍这么多,明天我们讲一下es6对promise的扩展

友情链接:点击查看所有文章目录

友情链接:点击查看 JavaScript异步系列文章目录

你可能感兴趣的:(JavaScript异步)