You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Angular Service同步调用?解决菜单列表排序空指针报错

问题分析

你遇到的「Cannot read property 'sort' of null」错误,核心原因是异步操作的执行顺序问题。

当localStorage.getItem('menulist')返回空值时,你调用了SetMenuList(),但这个方法里的getRMA是异步的HTTP请求——它不会阻塞后续代码的执行。所以在请求还没返回数据、this.menulist还没被重新赋值的时候,你就已经执行了JSON.parse(this.menulist)和sort操作,这时候this.menulist还是null,自然会报错。从控制台输出也能看出来:错误先被打印,之后才出现请求返回的菜单数据,完全印证了这个顺序问题。

解决方案

我们需要确保只有在菜单数据完全获取并存储到localStorage之后,再执行解析和排序操作。这里有两种常用的处理方式:

方式一:把排序逻辑移到异步回调内部

直接将解析、排序的代码放到SetMenuList的subscribe回调里,确保数据准备好后再处理:

ngOnInit() {
  this.menulist = localStorage.getItem('menulist');
  if (this.menulist) {
    // 本地已有数据,直接解析排序
    this.processMenuList();
  } else {
    // 本地无数据,请求后再处理
    this.SetMenuList();
  }
}

SetMenuList() {
  this._UserspecificmenuaccessService.getRMA("driver")
    .subscribe((lst) => {
      if (lst && lst.length > 0) {
        localStorage.setItem('menulist', JSON.stringify(lst));
        this.menulist = localStorage.getItem('menulist');
        console.log(this.menulist);
        // 请求完成后处理排序
        this.processMenuList();
      }
    }, (error) => {
      console.error(error)
    });
}

// 抽离公共的解析排序逻辑
processMenuList() {
  this.jsonmenulist = JSON.parse(this.menulist);
  // 注意:修复排序逻辑,避免重复调用+字符串排序问题
  this.jsonmenulist.sort(function (a, b) {
    // 按mnuposno数字排序,避免字符串比较的误差
    return parseFloat(a.mnuposno) - parseFloat(b.mnuposno);
  });
}

方式二:使用async/await简化异步流程

如果习惯用Promise风格的异步处理,可以把Observable转换成Promise,用async/await来保证顺序:

async ngOnInit() {
  this.menulist = localStorage.getItem('menulist');
  if (!this.menulist) {
    // 等待异步请求完成再继续
    await this.SetMenuList();
  }
  // 此时menulist一定有值,放心处理
  this.processMenuList();
}

SetMenuList(): Promise<void> {
  return new Promise((resolve, reject) => {
    this._UserspecificmenuaccessService.getRMA("driver")
      .subscribe((lst) => {
        if (lst && lst.length > 0) {
          localStorage.setItem('menulist', JSON.stringify(lst));
          this.menulist = localStorage.getItem('menulist');
          console.log(this.menulist);
        }
        resolve();
      }, (error) => {
        console.error(error);
        reject(error);
      });
  });
}

processMenuList() {
  this.jsonmenulist = JSON.parse(this.menulist);
  this.jsonmenulist.sort((a, b) => parseFloat(a.mnuposno) - parseFloat(b.mnuposno));
}
额外小提醒

你原来的代码里有两次重复的sort调用:

this.jsonmenulist.sort(function (a, b) { return a.mnuposno > b.mnuposno; });
this.jsonmenulist = this.jsonmenulist.sort();

这不仅冗余,还存在逻辑问题:第二次sort()没有传比较函数,会按字符串默认排序,直接覆盖第一次的排序结果;而且第一次的比较函数返回布尔值,不符合sort要求的返回数字(负数/0/正数)的规范,改成用parseFloat转换后做数字减法才是正确的排序方式。

内容的提问来源于stack exchange,提问作者SamuraiJack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:23:08