# 异步任务的处理
- 在 Promise 出来之前处理异步一般都是传入回调函数来解决,或者使用事件监听的方式
- 下面以回调函数举个栗子:
| function requsetDate(url, resolve, reject) { |
| |
| setTimeout(() => { |
| if (url === 'https://nekoaimer.com') { |
| |
| resolve('success message') |
| } else { |
| |
| reject('failure message') |
| } |
| }, 2000) |
| } |
| |
| requsetDate('https://nekoaimer.com', |
| res => { |
| console.log(res) |
| }, |
| err => { |
| console.log(err) |
| }) |
在上面的解决方案中,我们确确实实可以解决请求函数得到结果之后,获取到对应的回调,但是它存在两个主要的问题:
- 第一,我们需要自己来设计回调函数、回调函数的名称、回调函数的使用等;
- 第二,对于不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐心去看别人的源码或者文档,以便可以理解它这个函数到底怎么用;
# 什么是 Promise?
| function requsetDate(url, resolve, reject) { |
| return new Promise((resolve, reject) => { |
| setTimeout(() => { |
| if (url === 'https://nekoaimer.com') { |
| |
| resolve('success message') |
| } else { |
| |
| reject('failure message') |
| } |
| }, 2000) |
| }) |
| } |
| |
| |
| |
| |
| requsetDate('https://nekoaimer.com') |
| .then(res => { |
| console.log(res) |
| }, err => { |
| console.log(err) |
| }) |
# Promise 三种状态
| |
| new Promise((resolve, reject) => { |
| |
| console.log("--------") |
| |
| resolve(`success`) |
| |
| console.log('********') |
| |
| |
| reject(`failure`) |
| }) |
| .then(res => { |
| |
| console.log(`res:, ${res}`) |
| }, err => { |
| console.log(`err:, ${err}`) |
| }) |
# Promise.resolve(params)
# 普通的值或者对象 pending -> fulfilled
| new Promise((resolve, reject) => { |
| resolve(`我是被传入的普通参数-> 字符串`) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
| new Promise((resolve, reject) => { |
| resolve({message: `我是被传入的普通参数-> 对象`}) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
| new Promise((resolve, reject) => { |
| resolve(function foo (){ |
| console.log(`我是被传入的普通参数-> ${this}`) |
| }) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
| new Promise((resolve, reject) => { |
| resolve(() => { |
| console.log(`我是被传入的普通参数-> ${this}`) |
| }) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
# Promise
- 传入一个 Promise : 那么当前的 Promise 的状态会由传入的 Promise 来决定,相当于状态进行了移交
| const newPromise = new Promise((resolve, reject) => { |
| |
| reject('newPromise reject') |
| }) |
| |
| new Promise((resolve, reject) => { |
| |
| resolve(newPromise) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
| .catch(err => { |
| |
| console.log(err) |
| }) |
# thenable
- 传入一个对象,并且这个对象有实现 then 方法 (并且这个对象是实现了 thenable 接口) 那么也会执行该 then 方法,并且又该 then 方法决定后续状态
| new Promise((resolve, reject) => { |
| const obj = { |
| then: function (resolve, reject) { |
| resolve('obj*-*resolve~') |
| }, |
| catch: (resolve, reject) => { |
| reject('resolve') |
| } |
| } |
| |
| |
| resolve(obj) |
| }) |
| |
| .then(res => { |
| console.log(`res-> ${res}`) |
| }) |
| |
| |
| |
| |
| |
# Promise.then()
# then 多次调用
- 一个 Promise 的 then 方法可以被多次调用:
- 每次调用我们都可以传入对应的 fulfilled 回调
- 当 Promise 的状态变成 fulfilled 的时候,这些回调函数都会被执行
| |
| const promise = new Promise((resolve, reject) => { |
| resolve(i = 0) |
| }) |
| |
| promise.then(res => { |
| console.log(`第${++res}次调用`) |
| }) |
| |
| promise.then(res => { |
| console.log(`第${res + 2}次调用`) |
| }) |
| |
| promise.then(res => { |
| console.log(`第${res + 3}次调用`) |
| }) |
# then 返回值
- then 方法本身是有返回值的,它的返回值是一个 Promise
- 如果我们返回的是一个普通值 (数值 / 字符串 / 普通对象 /undefined), 那么这个普通的值被作为一个新的 Promise 的 resolve 值
# then 返回值是普通值
| new Promise((resolve, reject) => { |
| resolve(233) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
| |
| |
| new Promise((resolve, reject) => { |
| resolve(233) |
| }) |
| .then(res => { |
| console.log(res) |
| return 'lain' |
| }) |
| .then(res => { |
| console.log('lain') |
| }) |
| |
| .then(res => { |
| console.log(res) |
| }) |
# then 返回值是 Promise
| new Promise((resolve, reject) => { |
| resolve() |
| }) |
| .then(res => { |
| |
| return new Promise((resolve, reject) => { |
| setTimeout(() => { |
| resolve(2333) |
| }, 2000) |
| }) |
| }) |
| .then(res => { |
| console.log(res) |
| }) |
# then 返回值是实现 thenable 的对象
- 如果返回的是一个对象,并且该对象实现了 thenable
| new Promise((resolve, reject) => { |
| resolve() |
| }) |
| .then(res => { |
| |
| return { |
| then: function (resolve, reject) { |
| resolve(2333) |
| } |
| } |
| }) |
| .then(res => { |
| console.log(`res: ${res}`) |
| }) |
- 但是 then 方法返回的 Promise 到底处于什么样的状态呢?
- Promise 有三种状态,那么这个 Promise 处于什么状态呢?
- 当 then 方法中的回调函数本身在执行的时候,那么它处于 pending 状态;
- 当 then 方法中的回调函数返回一个结果时,那么它处于 fulfilled 状态,并且会将结果作为 resolve 的参数;
- 情况一:返回一个普通的值;
- 情况二:返回一个 Promise;
- 情况三:返回一个 thenable 值;
- 当 then 方法抛出一个异常时,那么它处于 reject 状态;
# Promise.catch()
# then 第二个参数 catch
- 第一个执行执行 resolve, 第二个参数执行 reject
| new Promise((resolve, reject) => { |
| reject('Reject Status') |
| }) |
| .then(null, err => { |
| console.log(err) |
| }) |
- 当 then 抛出异常时,那么它处于 reject 状态,也是会调用错误 (拒绝) 捕获的回调函数的
| new Promise((resolve, reject) => { |
| throw new Error('Reject Status') |
| }) |
| .then(null, err => { |
| console.log(err) |
| console.log(`----------`) |
| }) |
# catch 优先捕获自身异常
- 通过 catch 方法来传入错误 (拒绝) 捕获的回调函数
- 通过上面我们都知道 then 方法是返回一个新的 Promise,而 catch 默认情况下会先捕获自身的 Promise
- 举个栗子
| new Promise((resolve, reject) => { |
| throw new Error('Reject Status') |
| }) |
| |
| |
| .then(res => { |
| console.log(res) |
| return res |
| }) |
| |
| .catch(err => { |
| console.log(err) |
| }) |
- catch 默认优先捕获 new Promise 的异常, 注释掉第一个 Promise, 才会捕获第二个 Promise 抛出的异常
| new Promise((resolve, reject) => { |
| |
| |
| resolve() |
| }) |
| .then(res => { |
| |
| return new Promise((resolve, reject) => { |
| throw new Error('Reject Status2') |
| }) |
| }) |
| |
| .catch(err => { |
| console.log(err) |
| }) |
# 抛出异常未捕获到处理异常 (catch)
| const promise = new Promise((resolve, reject) => { |
| reject(233) |
| }) |
| |
| promise.then(res => { |
| console.log(res); |
| }) |
| |
| |
- 优先捕获自身处理的异常 (catch), 没找到就会找 then 返回的新的 Promise 的 catch
| const promise = new Promise((resolve, reject) => { |
| reject(233) |
| }) |
| |
| promise.then(res => { |
| console.log(res); |
| }) |
| |
| .catch(err => { |
| console.log('then返回新的Promise的catch', err) |
| }) |
| const promise = new Promise((resolve, reject) => { |
| reject(233) |
| }).catch(err => { |
| console.log('自身Promise的catch', err) |
| }) |
| |
| promise.then(res => { |
| console.log(res); |
| }) |
| .catch(err => { |
| console.log('then返回的新的Promise的catch', err) |
| }) |
# 抛出异常的执行顺序
| const promise = new Promise((resolve, reject) => { |
| reject('reject') |
| console.log(`---------`) |
| throw new Error('throw new Error') |
| }) |
| .catch(err => { |
| console.log(err) |
| }) |
| |
| |
| |
| |
- throw new Error 优先的情况下 不会执行下面的代码 类似 return 了
| const promise = new Promise((resolve, reject) => { |
| throw new Error('throw new Error') |
| console.log(`---------`) |
| reject('reject') |
| }) |
| .catch(err => { |
| console.log(err) |
| }) |
| |
| |
| |
# Catch 返回值
- 事实上 catch 方法也是会返回一个 Promise 对象的,所以 catch 方法后面我们可以继续调用 then 方法或者 catch 方法:
- 下面的代码,后续是 catch 中的 err2 打印,还是 then 中的 res2 打印?
| new Promise((resolev, reject) => { |
| reject('23333') |
| }) |
| .then(res1 => { |
| console.log(`res1`, res1) |
| }) |
| .catch(err1 => { |
| console.log('catch err1 -> ', err1) |
| return 'catch return value' |
| }) |
| .then(res2 => { |
| console.log(`res2 then -> `, res2) |
| }) |
| .catch(err2 => { |
| console.log(`err2 catch -> `, err2) |
| }) |
| new Promise((resolev, reject) => { |
| reject('23333') |
| }) |
| .then(res1 => { |
| console.log(`res1`, res1) |
| }) |
| .catch(err1 => { |
| console.log('catch err1 -> ', err1) |
| |
| throw new Error('catch throw new Error') |
| }) |
| .then(res2 => { |
| console.log(`res2 then -> `, res2) |
| }) |
| .catch(err2 => { |
| console.log(`err2 catch -> `, err2) |
| }) |
未完待续......