Promise回调处理和简洁的处理方案
Promise 提供了强大的异步编程能力,通过合理的链式调用、async/await 语法糖和各种静态方法,可以编写出既简洁又易于维护的异步代码。结合高级模式如错误处理中间件、超时控制和重试机制,可以构建更健壮的异步应用。选择哪种方式取决于具体场景和个人偏好,但 async/await 通常是使代码最接近同步风格的选择,特别适合复杂的异步逻辑。而 Promise 的静态方法则非常适合处理多个并行的
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.总是返回 Promise:在 then 回调中返回新的 Promise 或值,以保持链式调用
- 2.避免嵌套 Promise:使用链式调用或 async/await 替代嵌套
- 3.不要忽略错误:总是处理 catch 或使用 try/catch 包裹 await
- 4.合理使用 finally:清理资源或执行无论成功失败都需要的工作
- 5.命名 Promise 函数:给返回 Promise 的函数起描述性名称,提高可读性
总结
Promise 提供了强大的异步编程能力,通过合理的链式调用、async/await 语法糖和各种静态方法,可以编写出既简洁又易于维护的异步代码。结合高级模式如错误处理中间件、超时控制和重试机制,可以构建更健壮的异步应用。
选择哪种方式取决于具体场景和个人偏好,但 async/await 通常是使代码最接近同步风格的选择,特别适合复杂的异步逻辑。而 Promise 的静态方法则非常适合处理多个并行的异步操作。
更多推荐
所有评论(0)