Я пытаюсь прочитать элемент (список меню) из localStorage. Если он равен нулю, я вызываю службу, которая сохранит список меню после его извлечения из базы данных).
Кажется, что служба асинхронна, поскольку я получаю Cannot read property 'sort' of null в следующем коде.
ngOnInit() {
this.menulist = localStorage.getItem('menulist');
if (!this.menulist) {
this.SetMenuList();
}
this.jsonmenulist = JSON.parse(this.menulist);
this.jsonmenulist.sort(function (a, b) {
return a.mnuposno > b.mnuposno;
});
this.jsonmenulist = this.jsonmenulist.sort();
}
SetMenuList() {
this._UserspecificmenuaccessService.getRMA("driver")
.subscribe((lst) => {
if (lst && lst.length > 0) {
localStorage.setItem('menulist', JSON.stringify(lst));
this.menulist = localStorage.getItem('menulist');
console.info(this.menulist); // gets called after this.jsonmenulist.sort?
return true;
}
}, (error) => {
console.error(error)
});
}
Приставка:
ERROR TypeError: Cannot read property 'sort' of null
[{"mnurecid":"4","mnuid":"menu1","mnuname":"Bin","mnuurl":"/bin/","mnuposno":"1.0","checked":true}, {"mnurecid":"12","mnuid":"menu9","mnuname":"Menu9","mnuurl":"/menu9","mnuposno":"9.0","checked":false}]



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете написать код, который необходимо выполнить, внутри функции подписки, чтобы он выполнялся только после выполнения асинхронной операции.
Я мог бы. Но я хотел знать, какие у меня есть варианты.
Вы можете использовать метод обещать() из библиотека rxjs, чтобы вернуть обещание, а не наблюдаемое.
Итак, к вашим услугам
getRMA(type) {
return this.http.post(environment.baseURL + '/getmenulist', { drive:
type }, this.options).map((response) => response.json()
).toPromise().catch(e => {
console.info(e);
)}
}
и в вашем компоненте используйте async и ждать
async SetMenuList() {
let response = await
this._UserspecificmenuaccessService.getRMA("driver")
console.info(response)
}
Не совсем в отношении проблемы с асинхронный, вы просто используете this.menulist до того, как он будет назначен. Просто измените способ запуска кодов.
ngOnInit() {
this.menulist = localStorage.getItem('menulist');
if (this.menulist) {
this.sortMenuList(); // Sorting the menu if we have menulist already
} else {
this.SetMenuList(); // Else call the service and sort the menu then
}
}
sortMenuList() {
this.jsonmenulist = JSON.parse(this.menulist);
this.jsonmenulist.sort(function (a, b) {
return a.mnuposno > b.mnuposno;
});
this.jsonmenulist = this.jsonmenulist.sort();
}
SetMenuList() {
this._UserspecificmenuaccessService.getRMA("driver")
.subscribe((lst) => {
if (lst && lst.length > 0) {
localStorage.setItem('menulist', JSON.stringify(lst));
this.menulist = localStorage.getItem('menulist');
this.sortMenuList(); // Sorting the menu if we have menulist already
}
}, (error) => {
console.error(error)
});
}
Кстати, имя SetMenuList должно быть setMenuList (рекомендуется только для именования).
Вы не можете. Возможный дубликат stackoverflow.com/questions/14220321/… и stackoverflow.com/questions/43055706/…. Простой способ улучшить это - переключиться с наблюдаемых на обещания и использовать async / await в ngOnInit.