0
点赞
收藏
分享

微信扫一扫

Vue Promise((resolve, reject)

function generateRoutes() {
    return new Promise<RouteRecordRaw[]>((resolve, reject) => {
      MenuAPI.getRoutes()
        .then((data) => {
          const dynamicRoutes = parseDynamicRoutes(data);
          routes.value = [...dynamicRoutes];
          isRoutesLoaded.value = true;
          resolve(dynamicRoutes);
        })
        .catch((error) => {
          reject(error);
        });
    });
}

这个方法是用来动态生成前端路由的异步函数。让我详细解释它的作用:

功能说明

  1. 异步获取路由配置:通过 MenuAPI.getRoutes() 从后端API获取路由数据
  2. 解析路由数据:将后端返回的数据转换为前端可用的路由格式
  3. 更新应用状态:将生成的路由保存到应用中并标记路由已加载

代码流程

function generateRoutes(): Promise<RouteRecordRaw[]> {
  return new Promise((resolve, reject) => {
    // 1. 调用API获取路由数据
    MenuAPI.getRoutes()
      .then((data) => {
        // 2. 解析后端返回的路由数据
        const dynamicRoutes = parseDynamicRoutes(data);
        
        // 3. 更新本地状态(可能是Vue reactive变量)
        routes.value = [...dynamicRoutes];
        isRoutesLoaded.value = true;
        
        // 4. 返回解析后的路由
        resolve(dynamicRoutes);
      })
      .catch((error) => {
        // 错误处理
        reject(error);
      });
  });
}

使用场景

这种方法常用于:

  • 权限管理系统:根据不同用户角色返回不同的可访问路由
  • 动态菜单:根据用户权限动态生成侧边栏菜单
  • 微前端架构:动态加载子应用的路由

类型说明

  • RouteRecordRaw:通常是Vue Router的路由记录类型
  • routes.value:暗示使用了Vue的ref或类似响应式状态管理
  • isRoutesLoaded.value:用于标识路由是否已加载完成的标志

调用示例

// 在路由守卫或应用初始化时调用
generateRoutes()
  .then((routes) => {
    // 将动态路由添加到路由器中
    router.addRoute(routes);
  })
  .catch((error) => {
    console.error('路由加载失败', error);
  });

这是一个典型的前端动态路由解决方案,实现了路由的按需加载和权限控制。

(resolve, reject) 参数的作用

这两个参数是 Promise 构造函数自动提供的回调函数:

  • resolve:成功时调用,将 Promise 状态变为 fulfilled(已完成)
  • reject:失败时调用,将 Promise 状态变为 rejected(已拒绝)

如果不加 resolve(dynamicRoutes) 的后果

1. Promise 永远处于 pending 状态

// 调用这个函数后:
generateRoutes().then(routes => {
  console.log('这里永远不会执行'); // ❌ 不会执行
}).catch(error => {
  console.log('这里也不会执行'); // ❌ 不会执行
});

2. 内存泄漏

  • Promise 永远不会被解决,相关的内存无法被垃圾回收
  • 所有等待这个 Promise 的代码都会被阻塞

3. 路由无法使用

// 应用初始化代码
async function initApp() {
  await generateRoutes(); // ❌ 这里会永远等待
  router.addRoute(dynamicRoutes); // ❌ 永远不会执行
  app.mount('#app'); // ❌ 应用无法正常挂载
}

4. UI 界面卡住

  • 加载动画会一直显示
  • 用户看不到任何内容
  • 应用看起来像是"卡死了"

正确的 Promise 使用方式

function generateRoutes() {
  return new Promise((resolve, reject) => {
    MenuAPI.getRoutes()
      .then((data) => {
        const dynamicRoutes = parseDynamicRoutes(data);
        routes.value = [...dynamicRoutes];
        isRoutesLoaded.value = true;
        
        // 必须调用 resolve!否则 Promise 永远不会完成
        resolve(dynamicRoutes);
      })
      .catch((error) => {
        // 也必须调用 reject!否则错误会被吞掉
        reject(error);
      });
  });
}

简化写法(推荐)

其实可以不用 new Promise,直接返回 API 调用:

async function generateRoutes() {
  try {
    const data = await MenuAPI.getRoutes();
    const dynamicRoutes = parseDynamicRoutes(data);
    routes.value = [...dynamicRoutes];
    isRoutesLoaded.value = true;
    return dynamicRoutes;
  } catch (error) {
    throw error; // 自动 reject
  }
}

总结:不加 resolve() 会导致 Promise 永远处于等待状态,整个异步流程会被阻塞,应用无法正常工作。

resolve(dynamicRoutes); 可以把dynamicRoutes 换成 其它值

可以,但要注意类型和用途

是的,resolve(dynamicRoutes) 中的 dynamicRoutes 可以替换为其他值,但需要考虑以下几个方面:

1. 类型必须匹配

// 函数声明指定了返回 Promise<RouteRecordRaw[]>
function generateRoutes(): Promise<RouteRecordRaw[]> {
  return new Promise<RouteRecordRaw[]>((resolve, reject) => {
    // 必须返回 RouteRecordRaw[] 类型或兼容的类型
    resolve(dynamicRoutes); // ✅ 正确
    resolve([]); // ✅ 空数组也是 RouteRecordRaw[]
    resolve([{ path: '/', component: Home }]); // ✅ 直接传数组
  });
}

2. 可以返回的值示例

✅ 允许的返回值:

// 返回空数组
resolve([]);

// 返回静态路由
resolve([{ path: '/home', component: Home }]);

// 返回处理后的数据
resolve(processRoutes(data));

// 返回固定的路由结构
resolve([{
  path: '/dashboard',
  name: 'Dashboard',
  component: () => import('@/views/Dashboard.vue')
}]);

❌ 不允许的返回值:

resolve(null); // ❌ 类型不匹配
resolve("字符串"); // ❌ 类型不匹配  
resolve({}); // ❌ 对象不是数组
resolve(undefined); // ❌ 类型不匹配

3. 实际应用场景

场景1:返回空路由(无权限时)

resolve([]); // 用户没有任何权限时返回空数组

场景2:返回默认路由

resolve([{
  path: '/no-permission',
  component: NoPermission
}]);

场景3:返回处理后的数据

const filteredRoutes = dynamicRoutes.filter(route => 
  hasPermission(route.meta?.permission)
);
resolve(filteredRoutes);

4. 完整示例

function generateRoutes(): Promise<RouteRecordRaw[]> {
  return new Promise((resolve, reject) => {
    MenuAPI.getRoutes()
      .then((data) => {
        if (!data || data.length === 0) {
          // 没有数据时返回空数组
          resolve([]);
          return;
        }
        
        try {
          const dynamicRoutes = parseDynamicRoutes(data);
          
          // 过滤有权限的路由
          const accessibleRoutes = dynamicRoutes.filter(route => 
            checkPermission(route.meta?.permission)
          );
          
          routes.value = [...accessibleRoutes];
          isRoutesLoaded.value = true;
          
          // 返回过滤后的路由
          resolve(accessibleRoutes);
        } catch (error) {
          // 解析出错时返回默认路由
          resolve([{
            path: '/error',
            component: ErrorPage
          }]);
        }
      })
      .catch((error) => {
        // API 调用失败时返回空数组
        resolve([]);
        // 或者 reject(error);
      });
  });
}

5. 最佳实践建议

  1. 保持类型一致:返回的值必须符合 RouteRecordRaw[] 类型
  2. 错误处理:在 catch 中也要调用 resolve 或 reject,避免 Promise 挂起
  3. 默认值:考虑在出错时返回合理的默认值而不是让 Promise 挂起
  4. 日志记录:如果返回非预期值,最好记录日志以便调试

总结:可以替换 dynamicRoutes,但必须确保返回值的类型与函数声明的返回类型 Promise<RouteRecordRaw[]> 相匹配。


举报

相关推荐

0 条评论