Как загрузить несколько данных через службу и дождаться их в Angular2

Я использую Ionic 2 с Angular 2 в своем проекте. В корневом компоненте вы можете нажать кнопку «Добавить», чтобы добавить новый отчет через сложную форму и множество предварительно предоставленных данных (есть некоторые выборки, которые загружаются данными, извлеченными из базы данных sqlite). Теперь в моем «CreateReportComponent» у меня есть следующий конструктор для загрузки данных и присвоения их переменной локального массива:

selectEmployeeOptions: Employee[];

constructor(private dbService: DatabaseService) {
  dbService.getAllEmployees().then(employees => {
      this.selectEmployeeOptions = employees;
  });

  // load more data like tasks etc.
});

Но когда я хочу изменить эти данные в своем компоненте, массив пуст. Я пытался сделать это в ngOnInit(), но это тоже слишком рано.

Я хочу сделать что-то вроде этого, прежде чем компонент будет отображаться:

  dbService.getAllEmployees().then(employees => {
      this.selectEmployeeOptions = employees;

      // modify data
      this.selectEmployeeTitleOptions = employees.map((item) => {
         return item.title;
      });
      console.log(JSON.stringify(this.selectEmployeeTitleOptions)) // --> empty
  });

Но selectEmployeeTitleOptions пуст...

Функция в databaseService выглядит так:

getAllEmployees(): Promise<Emplyoee[]> {
  let query = "SELECT * FROM employees";
  let employeeList = [];
  this.database.executeSql(query, []).then((data) => {
     if(data.rows.length > 0) {
       let e = new Employee();
       e.id = data.rows.item(i).id;
       e.firstname = data.rows.item(i).firstname;
       e.lastname = data.rows.item(i).lastname;
       employeeList.push(e);
     }
  }, (error) => {
     // handle error
  });
  return Promise.resolve(employeeList);
}

Я читал, что есть шаблон Resolve (https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html) Но мне нужно сделать несколько вызовов и не только для контакты как в примере.

Итак, вопрос: как дождаться нескольких обращений к базе данных?


person GrübelDübel    schedule 02.02.2017    source источник


Ответы (3)


я думаю, что что-то здесь не так

getAllEmployees(): Promise<Emplyoee[]> {
  let query = "SELECT * FROM employees";
  let employeeList = [];
  this.database.executeSql(query, []).then((data) => {
     if(data.rows.length > 0) {
       let e = new Employee();
       e.id = data.rows.item(i).id;
       e.firstname = data.rows.item(i).firstname;
       e.lastname = data.rows.item(i).lastname;
       employeeList.push(e);
     }
  }, (error) => {
     // handle error
  });
  return Promise.resolve(employeeList);
}

первый return Promise.resolve(employeeList); вернет пустой массив, потому что это асинхронный процесс. вам нужен цикл через data.rows, а затем отформатируйте возвращаемые данные следующим образом.

getAllEmployees(): Promise<Employee[]> {
  let query = "SELECT * FROM employees";
  return this.database.executeSql(query, []).then((data) => {
    let arr = [];
    for(let i = ; i < data.rows.length; ++i) {
      let emp = data.rows.item(i);
      let e = new Employee();
      e.id = emp.id;
      e.firstname = emp.firstname;
      e.lastname = emp.lastname;
      arr.push(e);
    }
    return arr;
  });
}

обратите внимание, что .then() вернуть объект обещания.

person Tiep Phan    schedule 02.02.2017
comment
Спасибо. Я пробовал это, но получаю сообщение об ошибке: TypeError: data.rows.map не является функцией - person GrübelDübel; 02.02.2017
comment
не могли бы вы указать значение data.rows (вывести на консоль)? - person Tiep Phan; 02.02.2017
comment
Конечно. data.rows – это {length:3}, тогда как data – это {rows:{length:3},rowsAffected:0}. - person GrübelDübel; 02.02.2017
comment
как перебрать все строки - person Tiep Phan; 02.02.2017
comment
сделать снимок экрана, а затем загрузить куда-нибудь - person Tiep Phan; 02.02.2017
comment
Единственный способ получить элементы массива - это один из моих примеров. вызвав data.rows.item(i)... - person GrübelDübel; 02.02.2017

То, что вы ищете, - это метод forkJoin, который возвращает Observable, на который вы должны переключиться вместо использования Promises, для справки о том, почему вы должны сделать эту проверку здесь.

Краткая информация о форк-соединении со страницы GitHub:

Запускает все наблюдаемые последовательности параллельно и собирает их последние элементы.

Таким образом, вы можете безопасно делать параллельные запросы к вашему API.

Для получения дополнительной информации о forkJoin перейдите здесь< /а>.

Кроме того, вы должны вызывать службы с помощью ngOnInit, как вы упоминали ранее. Дополнительные сведения о хуках жизненного цикла Angular 2 см. в документах.

person Gorsky    schedule 02.02.2017
comment
Я постараюсь пойти с ответом @tiep-phan. Но я воспользуюсь твоим последним советом. Спасибо :) - person GrübelDübel; 02.02.2017

Вы можете использовать Promise.all https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Вы помещаете все промисы в массив, а затем переходите

    let foo : [Promise<Emplyoee[]>,Promise<void>] = [getAllEmployees(), method2()];
    Promise.all(foo).then((results:any[]) => {
       let employeearray: any = results[0];
       /* and on an on */
     });
person n00b    schedule 02.02.2017