Асинхронная модель Ember.js

У меня есть текстовый файл, который я использую для создания таблицы с помощью таблицы ember-models (https://github.com/onechiporenko/ember-models-table). У меня есть функция, которая преобразует файл в объект json. У меня возникли трудности с асинхронной загрузкой. Я хочу, чтобы страница с заголовками таблицы загружалась немедленно, а данные отображались после ее загрузки. То, что у меня сейчас есть, ничего не отображает, пока данные не будут загружены. Что я делаю неправильно? Спасибо за помощь.

import Ember from 'ember';

function getData(columns, url, deliminator) {
  return Ember.$.get(url).then(function(file) {
    var data = [];
    var headers = [];
    var lines = file.split("\n");

    for(var i = 0; i < columns.length; i++){
      headers[i] = columns[i].propertyName;
    }

    for(var j = 0; j < lines.length; j++){
      var obj = {};
      var currentline = lines[j].split(deliminator);

      for(var k = 0; k < headers.length; k++){
        obj[headers[k]] = currentline[k];
      }

      data.push(obj);
    }

    return data;
  });
}

export default Ember.Route.extend({
  model() {
    var columns = [
      {
        "propertyName": "date",
        "title": "Date/Time"
      },
      {
        "propertyName": "application",
        "title": "Application"
      },
      {
        "propertyName": "priority",
        "title": "Priority"
      },
      {
        "propertyName": "message",
        "title": "Message"
      }
    ];

    var url = 'http://localhost:4200/Errors.log';
    var deliminator = '|';
    return getData(columns, url, deliminator).then(function(data) {
      return {columns, data};
    });
  }
});

person Alec Fenichel    schedule 15.10.2015    source источник


Ответы (1)


Предполагая, что модели ember table будут правильно обновляться, хитрость заключается в том, чтобы не возвращать обещание, а немедленно возвращать объект и асинхронно обновлять объект постфактум.

Заполнить данные

function populateData(columns, url, deliminator, data) {
  Ember.$.get(url).then(function(file) {
    var headers = [];
    var lines = file.split("\n");

    for(var i = 0; i < columns.length; i++){
      headers[i] = columns[i].propertyName;
    }

    for(var j = 0; j < lines.length; j++){
      var obj = {};
      var currentline = lines[j].split(deliminator);

      for(var k = 0; k < headers.length; k++){
        obj[headers[k]] = currentline[k];
      }

      // this is important here, you want to use pushObject instead of push
      data.pushObject(obj);
    }
  });
}

Маршрут

export default Ember.Route.extend({
  model() {
    var columns = [
      {
        "propertyName": "date",
        "title": "Date/Time"
      },
      {
        "propertyName": "application",
        "title": "Application"
      },
      {
        "propertyName": "priority",
        "title": "Priority"
      },
      {
        "propertyName": "message",
        "title": "Message"
      }
    ];

    var url = 'http://localhost:4200/Errors.log',
        deliminator = '|',
        data = [];
    populateData(columns, url, deliminator, data);

    // ES6 Enhanced Object Properties, Property Shorthand
    return {columns, data};
  }
});

Небольшая доработка с заменой массива

function getData(columns, url, deliminator) {
  return Ember.$.get(url).then(function(file) {
    var headers = [];
    var data = [];

    var lines = file.split("\n");

    for(var i = 0; i < columns.length; i++){
      headers[i] = columns[i].propertyName;
    }

    for(var j = 0; j < lines.length; j++){
      var obj = {};
      var currentline = lines[j].split(deliminator);

      for(var k = 0; k < headers.length; k++){
        obj[headers[k]] = currentline[k];
      }

      // this is important here, you want to use pushObject instead of push
      data.push(obj);
    }
    return data;
  });
}

Маршрут

export default Ember.Route.extend({
  model() {
    var columns = [
      {
        "propertyName": "date",
        "title": "Date/Time"
      },
      {
        "propertyName": "application",
        "title": "Application"
      },
      {
        "propertyName": "priority",
        "title": "Priority"
      },
      {
        "propertyName": "message",
        "title": "Message"
      }
    ];

    var url = 'http://localhost:4200/Errors.log',
        deliminator = '|',
        dataObj = { data: [] };

    getData(columns, url, deliminator).then(data => Ember.set(dataObj, 'data', data));

    // ES6 Enhanced Object Properties, Property Shorthand
    return {columns, dataObj};
  }
});

Внутри вашего шаблона вы должны ссылаться на {{model.dataObj.data}} вместо {{model.data}}

person Kingpin2k    schedule 15.10.2015
comment
Так что теперь он сразу загружает страницу и заголовки, но затем зависает, и данные никогда не загружаются. Это заставляет мой браузер (Chrome) зависать, и я должен принудительно закрыть его. На консоли ничего не появляется. Есть идеи? - person Alec Fenichel; 15.10.2015
comment
Ого, впечатляет, если через него отлаживать, то с чего начинает крутиться? - person Kingpin2k; 15.10.2015
comment
Так что это на самом деле работает, но так невероятно медленно, что кажется, что он падает. Если файл с разделителями вертикальной черты содержит 500 строк, это занимает почти 30 секунд. Есть идеи, почему изменение так сильно уменьшило скорость? Я предполагаю, что это как-то связано с pushObject , но я не знаю, что. - person Alec Fenichel; 16.10.2015
comment
pushObject сообщает ember, что вы добавили элемент в коллекцию. Если вы просто используете push, он не будет знать, что коллекция изменилась, и не будет обновлять какие-либо зависимые элементы. Я предполагаю, что что-то с таблицами моделей ember очень медленно добавляет элементы постфактум. вполне возможно, что вместо заполнения массива постфактум замена полностью заполненного массива постфактум может оказаться более эффективной. подкину пример - person Kingpin2k; 16.10.2015
comment
Я получаю следующую ошибку при переходе к маршруту: Ошибка при обработке маршрута: Dashboard.logs.error Не удается прочитать свойство «затем» из неопределенного TypeError: Невозможно прочитать свойство «затем» из неопределенного vendor.js: 39394 Ошибка: Дополнительные объекты контекста были переданы, то есть динамические сегменты для маршрута: Dashboard.logs.error vendor.js:39394 TypeError: Не удается прочитать свойство «тогда» неопределенного - person Alec Fenichel; 19.10.2015
comment
Вы поместите свою реализацию в вопрос - person Kingpin2k; 20.10.2015
comment
Я где-то сделал опечатку, я просто повторил попытку, и это сработало отлично. Немного медленно с большими столами, но достаточно хорошо! Я сделаю так, чтобы в первой строке было написано «Загрузка» и «Готово». Спасибо! - person Alec Fenichel; 20.10.2015