Как вызвать синхронизацию Angular Service?

Я пытаюсь прочитать элемент (список меню) из 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}]

Вы не можете. Возможный дубликат stackoverflow.com/questions/14220321/… и stackoverflow.com/questions/43055706/…. Простой способ улучшить это - переключиться с наблюдаемых на обещания и использовать async / await в ngOnInit.

Estus Flask 18.05.2018 08:41
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
1 064
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете написать код, который необходимо выполнить, внутри функции подписки, чтобы он выполнялся только после выполнения асинхронной операции.

Я мог бы. Но я хотел знать, какие у меня есть варианты.

SamuraiJack 18.05.2018 08:44

Вы можете использовать метод обещать() из библиотека 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 (рекомендуется только для именования).

Другие вопросы по теме