AngularJS中 then catch finally 的语义、执行规则与推荐写法

一、整体认知:AngularJS 中的 Promise 链模型

在 AngularJS 中:

  • then / catch / finally 属于 $q Promise 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();
  });

规则:

  1. finally 不接收参数
  2. finally 返回值 不会改变链条结果
  3. 抛异常 → 覆盖原状态(需谨慎)

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;
    });
}

六、强烈推荐的工程写法总结

✅ 推荐

  1. then:只做"值转换"
  2. 同步函数直接 return
  3. 异步函数必须 return Promise
  4. catch:集中、链尾
  5. finally:只做状态清理

❌ 不推荐

反模式 问题
then(success, error) 破坏错误冒泡
then 中写控制流 可读性差
finally 改业务数据 语义混乱
then 中不 return 隐式 undefined

七、一句话总结

在 AngularJS 中,then 负责"算值",catch 负责"兜底",finally 负责"收尾",三者各司其职,链条才是可维护的。

相关推荐
酉鬼女又兒2 小时前
SQL113+114 更新记录(一)(二)+更新数据知识总结
java·服务器·前端
利刃大大2 小时前
【Vue】组件化 && 组件的注册 && App.vue
前端·javascript·vue.js
Whisper_Sy2 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 周报告实现
开发语言·javascript·网络·flutter·php
Anastasiozzzz2 小时前
leetcodehot100--最小栈 MinStack
java·javascript·算法
一起养小猫2 小时前
Flutter for OpenHarmony 实战:按钮类 Widget 完全指南
前端·javascript·flutter
css趣多多2 小时前
Vux store实例的模块化管理
前端
我是伪码农3 小时前
Vue 1.26
前端·javascript·vue.js
晚霞的不甘4 小时前
Flutter for OpenHarmony 创意实战:打造一款炫酷的“太空舱”倒计时应用
开发语言·前端·flutter·正则表达式·前端框架·postman
2601_949480064 小时前
Flutter for OpenHarmony音乐播放器App实战:定时关闭实现
javascript·flutter·原型模式