前言

回调 一直是JavaScript编程中比较令人纠结的写法,主要场景是用于处理 “并列”或者“并行”的操作,然后在回调函数中处理操作结果。这样子原生的回调写法就会带来一下的不便。

  • 回调结果状态不便管理
  • 回调方式自由松散,没有规范约束

例如下面的回调的写法

  1. function func(num, callback) {
  2. setTimeout(() => {
  3. try {
  4. let result = 1/num;
  5. callback(result, null);
  6. } catch(err) {
  7. callback(null, err);
  8. }
  9. }, 10)
  10. }
  11. func(1, (result, err) => {
  12. if( err ) {
  13. console.log(err)
  14. } else {
  15. console.log(result)
  16. }
  17. })

上述代码中,发现如果要处理回调结果 result和错误err ,后续的所有就必须在回调函数里面处理,而且回调函数里面还需要自己处理异常判断。 那如果是使用了Promise来处理回调操作,就可以用以下写法处理。

  1. function func(num, callback) {
  2. return new Promise((resolve) => {
  3. setTimeout(() => {
  4. let result = 1/num;
  5. resolve(result);
  6. }, 1000)
  7. })
  8. }
  9. func(1).then((result) => {
  10. console.log(result)
  11. }).catch((err) => {
  12. console.log(err)
  13. })

Promise能力

Promise 带来的能力是任务管理,常用的方式有
new Promise(...).then(onResolved, onRejected)

  • 任务状态管理
    • resolve 成功状态,对应 Promise.resolve
    • reject 失败状态,对应 Promise.reject
    • error 异常状态, 对应 Promise.rejectnew Promise().catch(onRejected)
  • Thenabled机制提供任务方法链

    • new Promise().then().then().catch()

      resolve

      处理任务的成功状态
  • 普通方式

    1. let p = new Promise((resolve) => {
    2. setTimeout(() => {
    3. let result = 1;
    4. resolve(result);
    5. }, 1000)
    6. })
    7. p.then((result)=>{ console.log(result) })
  • 快捷方式

    1. let p = Promise.resolve(1)
    2. p.then((result)=>{ console.log(result) })

    reject

    处理任务的失败状态

  • 普通方式

    1. let p = new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. let result = 2;
    4. reject(result);
    5. }, 100)
    6. })
    7. // 有两种方式获取失败状态
    8. // 第一种,通过then 第二个函数参数处理失败状态
    9. p.then((result)=>{
    10. console.log('success:',result);
    11. }, (result)=>{
    12. console.log('fail:',result);
    13. })
    14. // "fail: 2"
    15. // 第二种,或者通过,catch 获取失败状态
    16. p.then((result)=>{
    17. console.log('success:',result);
    18. }).catch((result)=>{
    19. console.log('error:',result);
    20. })
    21. // "error: 2"
    22. // 注意:如果两种方式同时使用的话
    23. // 只会被第一种方式reject操作失败的结果
    24. p.then((result)=>{
    25. console.log('success:',result);
    26. }, (result)=>{
    27. console.log('fail:',result);
    28. }).catch((result)=>{
    29. console.log('error:',result);
    30. })
    31. // "fail: 2"
  • 快捷方式

    1. let p = Promise.reject(2)
    2. p.then(null, result => console.log('fail:', result))
    3. // 或
    4. p.then().catch( result => console.log('error:', result))

    catch

    从上述 reject 的使用过程中,会发现, catch操作在没有设置 onRejected 处理的时候,会被catch 捕获失败处理。同时catch 也会捕获 onResolved 和 onRejected中出现的错误。

  • 正常情况下直接捕获reject结果

    1. let p = new Promise((resolve, reject) => {
    2. reject(3)
    3. });
    4. p.then((result) => {
    5. console.log('success:', result)
    6. }).catch((result) => {
    7. console.log('error:', result)
    8. })
    9. // "error: 3"
  • 捕获 onResolved 中错误异常

    1. let p = new Promise((resolve) => {
    2. resolve(3)
    3. });
    4. p.then((result) => {
    5. throw new Error('custom resolve error!')
    6. console.log('success:', result)
    7. }).catch((err) => {
    8. console.log('Custom error:', err)
    9. })
    10. // "Custom error: Error: custom resolve error!"
  • 捕获 onRejected 中错误异常

    1. let p = new Promise((resolve) => {
    2. reject(3)
    3. });
    4. p.then(null, (result) => {
    5. throw new Error('custom reject error!')
    6. console.log('fail:', result)
    7. }).catch((err) => {
    8. console.log('Custom error:', err)
    9. })
    10. // "Custom error: Error: custom reject error!"

    后记

    由于本书主要介绍 Koa.js的原理,主要涉及到Promiseresolverejectcatch 更多 关于 Promise 的原理和使用,请查看一下文档:
    https://docs.microsoft.com/zh-cn/scripting/javascript/reference/promise-object-javascript