如何让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
相关产品推荐
相关产品推荐

