JasonWu73/Blog

解惑Promise与异步函数(async & await)的执行顺序

JasonWu73 opened this issue · 0 comments

Promise

常规

const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    resolve('6-success')
    reject('6-error')
    console.log('5')
  }, 10)

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
    .then((data) => console.log(data))
    .catch(error => console.log(error))
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 5 6-success
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    resolve('6-success')
    reject('6-error')
    console.log('5')
  }, 10)

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 5
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    reject('6-error')
    resolve('6-success')
    console.log('5')
  }, 10)

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
    .then((data) => console.log(data))
    .catch(error => console.log(error))
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 5 6-error
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    reject('6-error')
    resolve('6-success')
    console.log('5')
  }, 10)

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 5 Uncaught (in promise) 6-error

非常规

const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    console.log('6')
  }, 10)

  // 错误写法:将回调写在了异步方法之外
  reject('5-error')

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 Uncaught (in promise) 5-error 6
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    console.log('6')
  }, 10)

  // 错误写法:将回调写在了异步方法之外
  resolve('5-success')

  console.log('2')
})

const executeByPromise = () => {
  asyncMethod()
  console.log('3')
  console.log('4')
}
executeByPromise()

// 1 2 3 4 6

总结

Promise关联方法:resolve(value)reject(error)

Promise关联方法位于异步回调内:

  1. 按顺序执行完Promise中的同步方法
  2. 按顺序执行完Promise外的同步方法
  3. 当Promise内的异步方法执行完毕后,触发其回调函数
  4. 按顺序执行完回调函数中非Promise关联方法的同步方法
  5. 按顺序执行回调函数中Promise关联方法(resolvereject,哪个在前就执行哪个)
    - 若方法为resolve(error),则自动抛出错误error
    - 若方法为resolve(value),则只有通过then才能得到value

Promise关联方法位于异步回调外:

  1. 按顺序执行完Promise中的同步方法
  2. 按顺序执行完Promise外的同步方法
  3. 执行Promise关联方法
  • 若方法为resolve(error),则自动报出错误error
  • 若方法为resolve(value),则只通过then才能得到value
  1. 执行Promise内的异步方法

异步函数(async & await)

常规

const asyncMethod = () => new Promise(resolve => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    resolve('6-success')
    console.log('3')
  }, 10)

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log('4')
  console.log('5')
  console.log(result)
}
executeByKeyword()

// 1 2 3 4 5 6-success
const asyncMethod = () => new Promise(resolve => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    resolve('4-success')
    console.log('3')
  }, 10)

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log(result)
  console.log('5')
  console.log('6')
}
executeByKeyword()

// 1 2 3 4-success 5 6
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    reject('4-error')
    console.log('3')
  }, 10)

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log('5')
  console.log('6')
  console.log(result)
}
executeByKeyword()

// 1 2 3 Uncaught (in promise) 4-error

非常规

const asyncMethod = () => new Promise(resolve => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    console.log('6')
  }, 10)

  // 错误写法:将回调写在了异步方法之外
  resolve('3-success')

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log(result)
  console.log('4')
  console.log('5')
}
executeByKeyword()

// 1 2 3-success 4 5 6
const asyncMethod = () => new Promise(resolve => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    console.log('6')
  }, 10)

  // 错误写法:将回调写在了异步方法之外
  resolve('5-success')

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log('3')
  console.log('4')
  console.log(result)
}
executeByKeyword()

// 1 2 3 4 5-success 6
const asyncMethod = () => new Promise((resolve, reject) => {
  console.log('1')

  // 执行异步方法
  setTimeout(() => {
    console.log('6')
  }, 10)

  // 错误写法:将回调写在了异步方法之外
  reject('3-error')

  console.log('2')
})

const executeByKeyword = async () => {
  const result = await asyncMethod()
  console.log('4')
  console.log('5')
  console.log(result)
}
executeByKeyword()

// 1 2 Uncaught (in promise) 3-error 6

Promise关联方法位于异步回调内:

  1. 遇到await关键字时,按顺序执行完其表达式Promise中的同步方法
  2. 等待Promise中的异步方法执行完毕
  3. 按顺序执行完异步回调中非Promise关联方法的同步方法
  4. 执行异步回调中Promise关联方法
  • 当关联方法为reject(error)时,则直接抛出错误error
  1. 执行await表达式的下一条语句
  • 若使用了await表达式的结果,执行resolve(value)方法得到结果值value
  • 若没有使用await表达式的结果,执行该条语句,直到遇到使用该await表达式的结果值时,才调用resolve方法

Promise关联方法位于异步回调外:

  1. 遇到await关键字时,按顺序执行完其表达式Promise中的非Promise关联方法的同步方法
  2. 关联方法是否为reject(error)
  • 是,则直接抛出错误error
  1. 执行await表达式的下一条语句
  • 若使用了await表达式的结果,执行resolve(value)方法得到结果值value
  • 若没有使用await表达式的结果,执行该条语句,直到遇到使用该await表达式的结果值时,才调用resolve方法
  1. 执行Promise中的异步方法

Promise与Async函数的共同点

因为async/await只作为用来简化使用基本Promise API的语法,所以Promise的特性,在异步函数中同样有效。

  • Promise关联方法总是在其Promise范围内的其他同步方法之后才被执行
  • 哪怕没有显示地捕获错误,reject也会自动抛出错误
  • resolve在没有显示调用时,其回调值会被忽略
  • promise对象本身也是一个异步方法