Promise 是 JavaScript 中处理异步操作的核心机制,它解决了传统回调地狱(callback hell)的问题,但如果不合理使用,仍然可能导致代码难以维护。下面我将介绍 Promise 的回调处理和各种简洁解决方案。

一、Promise 基本回调处理

1.

Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。基本使用方式如下:

const promise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 成功 */) {
    resolve(value); // 状态变为fulfilled
  } else {
    reject(error); // 状态变为rejected
  }
});

promise
  .then(value => {
    // 成功回调
  })
  .catch(error => {
    // 失败回调
  })
  .finally(() => {
    // 无论成功失败都会执行
  });

2.

Promise的回调链式调用

主要利用了Promise对象的2个特性:1. Promise的then方法会返回一个新Promise对象  2.then方法的返回值会影响这个新的Promise对象的结果

链式编程中写出来的代码结构大概是这样子的,then和then之间都是平级的举个例子:

  promise对象
  .then(() => {
    // 内容1
  }).then(()=>{
    // 内容2
  }).then(()=>{
    // 内容3
  })

3.

async/await 语法糖

ES2017 引入的 async/await让Promise代码更同步化,与鸿蒙里的语法糖对比着使用可以对理解又帮助

async function foo() {
  try {
    const result = await doSomething();
    const newResult = await doSomethingElse(result);
    const finalResult = await doThirdThing(newResult);
    console.log(`最终结果: ${finalResult}`);
  } catch (error) {
    failureCallback(error);
  }
}

4.

Promise静态处理方法

1).Promise.resolve

返回一个成功原因的Promise对象

Promise.resolve('成功原因')
  .then(res => {
    AlertDialog.show({ message: res })
  })

2).Promise.reject

返回一个拒绝原因的Promise对象

Promise.reject('拒绝原因')
  .catch((err: string) => {
    AlertDialog.show({ message: err })
  })

3).Promise.race

传入 Promise 数组,返回第一个成功或者失败的结果

const p1 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('1')
  }, 2000)
})
const p2 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    reject('2')
  }, 1000)
})
Promise.race([p1, p2, 'itheima']).then((res) => {
  console.log('res:', res)
}, (err:string) => {
  console.log('err:', err)
})

4).Promise.all

传入 Promise 数组,等待所有 Promise 完成

const p1 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('1')
  }, 2000)
})
const p2 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    reject('2')
  }, 1000)
})
Promise.all([p1, p2, 'itheima'])
  .then((res) => {
    console.log('res:', res)
  }, (err: string) => {
    console.log('err:', err)
  })

二、高级处理模式

1. 错误处理中间件

function asyncHandler(fn) {
  return function(req, res, next) {
    return Promise.resolve(fn(req, res, next))
      .catch(next);
  };
}

// 使用示例
router.get('/path', asyncHandler(async (req, res) => {
  const data = await fetchData();
  res.json(data);
}));

2.超时控制

function withTimeout(promise, timeoutMs) {
  return Promise.race([
    promise,
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('操作超时')), timeoutMs)
    )
  ]);
}

// 使用
withTimeout(fetch('url'), 5000)
  .then(response => console.log(response))
  .catch(error => console.error(error));

3.重试机制

function retry(promiseFn, maxRetries = 3, delay = 1000) {
  return new Promise((resolve, reject) => {
    const attempt = (retryCount) => {
      promiseFn()
        .then(resolve)
        .catch(error => {
          if (retryCount < maxRetries) {
            console.log(`重试 ${retryCount + 1}/${maxRetries}`);
            setTimeout(() => attempt(retryCount + 1), delay);
          } else {
            reject(error);
          }
        });
    };
    attempt(0);
  });
}

// 使用
retry(() => fetch('unstable-api'), 5, 2000)
  .then(data => console.log(data))
  .catch(error => console.error('最终失败:', error));

最佳实践

  1. 1.​​总是返回 Promise​​:在 then 回调中返回新的 Promise 或值,以保持链式调用
  2. 2.​​避免嵌套 Promise​​:使用链式调用或 async/await 替代嵌套
  3. 3.​​不要忽略错误​​:总是处理 catch 或使用 try/catch 包裹 await
  4. 4.​​合理使用 finally​​:清理资源或执行无论成功失败都需要的工作
  5. 5.​​命名 Promise 函数​​:给返回 Promise 的函数起描述性名称,提高可读性

总结

Promise 提供了强大的异步编程能力,通过合理的链式调用、async/await 语法糖和各种静态方法,可以编写出既简洁又易于维护的异步代码。结合高级模式如错误处理中间件、超时控制和重试机制,可以构建更健壮的异步应用。

选择哪种方式取决于具体场景和个人偏好,但 async/await 通常是使代码最接近同步风格的选择,特别适合复杂的异步逻辑。而 Promise 的静态方法则非常适合处理多个并行的异步操作。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐