一、整体认知:AngularJS 中的 Promise 链模型
在 AngularJS 中:
then / catch / finally属于$qPromise API- 遵循 Promises/A+ 规范
- 与
$digest机制深度集成 - 用于描述"值如何一步步被计算出来"
可以将 Promise 链理解为:
一个"值"的流水线(value pipeline)
二、then ------ 值转换与流程推进
1. 规范定义
js
promise.then(onFulfilled, onRejected);
推荐使用:
js
promise.then(onFulfilled).catch(onRejected);
2. then 的核心语义(非常重要)
then 的职责只有一个:
接收上一步的结果,返回下一步的结果
3. 变量在 then 中的行为
(1)返回普通变量(同步值)
js
$q.when(10)
.then(function (value) {
return value + 5;
})
.then(function (result) {
// result === 15
});
规则:
- 返回值 → 自动
resolve - 不需要显式
$q.when
(2)返回对象 / 数组
js
.then(function (data) {
return {
id: data.id,
name: data.name
};
});
✔️ 完全合法
✔️ 不会拷贝,只传引用
4. 同步方法在 then 中的行为
示例:同步计算
js
function normalizeName(user) {
user.name = user.name.trim().toUpperCase();
return user;
}
getUser()
.then(normalizeName)
.then(saveUser);
说明:
- 同步函数可以直接作为
then回调 - 返回值自动包装为 Promise
- 推荐写法
5. 异步方法在 then 中的行为(重点)
示例:返回 Promise
js
function loadProfile(user) {
return $http.get('/profile/' + user.id)
.then(function (res) {
user.profile = res.data;
return user;
});
}
getUser()
.then(loadProfile)
.then(render);
规则:
then返回 Promise- 链条自动等待
- 严禁在 then 中手动 resolve
6. ❌ 不推荐的 then 写法
js
.then(function (data) {
doSomethingAsync(data, function (result) {
// 回调嵌套(反模式)
});
});
三、catch ------ 错误处理与错误边界
1. 规范定义
js
promise.catch(onRejected);
等价于:
js
promise.then(null, onRejected);
2. catch 的职责
捕获之前链条中任意位置的异常或 reject
来源包括:
$q.reject(reason)throw new Error()- 返回 rejected Promise
3. catch 中的变量与返回值
(1)不返回值(默认)
js
.catch(function (err) {
log(err);
});
- 链条到此结束
- 后续
then不再执行
(2)返回同步值(错误恢复)
js
.catch(function () {
return defaultValue;
})
.then(function (value) {
// value === defaultValue
});
✔️ 合法
✔️ 表示"错误被修复"
(3)返回 Promise(异步恢复)
js
.catch(function () {
return loadFromCache();
});
4. 推荐的 catch 写法(强烈)
js
promise
.then(step1)
.then(step2)
.then(step3)
.catch(handleError);
原则:
- 只在链尾使用 catch
- 不在中途吞异常
四、finally ------ 资源清理与状态收尾
1. 规范定义
js
promise.finally(onFinally);
2. finally 的语义
无论成功或失败都会执行,不接收链条的值
3. finally 中的行为规则
js
promise
.then(success)
.catch(error)
.finally(function () {
stopLoading();
});
规则:
finally不接收参数finally返回值 不会改变链条结果- 抛异常 → 覆盖原状态(需谨慎)
4. finally 中的同步与异步方法
同步清理(推荐)
js
.finally(function () {
vm.loading = false;
});
异步清理(谨慎)
js
.finally(function () {
return logAsync();
});
⚠️ 会延迟链条完成
五、综合示例(变量 + 同步 + 异步)
js
function processUser(id) {
return getUser(id) // 异步
.then(validateUser) // 同步
.then(loadProfile) // 异步
.then(function (user) { // 同步变量处理
user.ready = true;
return user;
})
.catch(function (err) { // 错误处理
report(err);
return fallbackUser; // 恢复
})
.finally(function () { // 状态收尾
vm.loading = false;
});
}
六、强烈推荐的工程写法总结
✅ 推荐
then:只做"值转换"- 同步函数直接 return
- 异步函数必须 return Promise
catch:集中、链尾finally:只做状态清理
❌ 不推荐
| 反模式 | 问题 |
|---|---|
then(success, error) |
破坏错误冒泡 |
then 中写控制流 |
可读性差 |
finally 改业务数据 |
语义混乱 |
then 中不 return |
隐式 undefined |
七、一句话总结
在 AngularJS 中,
then负责"算值",catch负责"兜底",finally负责"收尾",三者各司其职,链条才是可维护的。