Почему не отработал хук model и что теперь делать?

Первый вопрос: когда хук model не вызовется при переходе на роут?

Хук model используется для загрузки модели в текущем роуте. Не вызывается он только в одном случае — когда у роута есть «динамическая» часть и переход на него происходит через внутреннюю ссылку на странице. Почему так? Ember считает, что использующаяся модель уже есть в store и ее загружать не надо (ведь как-то ж ссылку с ее id получили). В других случаях («статический» роут или переход извне), хук model вызывается и нужная модель загружается.

Второй вопрос: в каких случаях «игнорирование» model может привести к проблемам? На ум приходит ситуация, когда в модели есть только часть данных. Пример: есть модель post и два роута:

// app/models/post.js
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
 
export default Model.extend({
  title: attr('string'),
  body: attr('string')
});
// app/router.js
Router.map(function() {
 
  this.route('posts', {path: '/posts'}, function () {
    this.route('post', {path: '/:post_id'});
  });
 
});
// app/routes/posts/index.js
import Ember from 'ember';
 
export default Ember.Route.extend({
  model() {
    return this.store.findAll('post');
  }
 
});
// app/routes/posts/post.js
import Ember from 'ember';
 
export default Ember.Route.extend({
 
  model(params) {
    return this.store.findRecord('post', params.post_id);
  }
 
});

Один выводит краткие сведения о всех заметках, а другой (вложенный) отображает все данные о выбранной. Если заметки очень большие, то нет смысла загружать их полностью на уровне posts, а лучше это делать при переходе к конкретной заметке. Ниже пример API-ответов:

// api call for "/posts"
{
  "data": [{
    "type": "post",
    "id": "1",
    "attributes": {
      "title": "Post #1"
    }
  }, {
    "type": "post",
    "id": "2",
    "attributes": {
      "title": "Post #2"
    }
  }]
}
 
//api call for "/posts/1"
{
  "data": {
    "type": "post",
    "id": "1",
    "attributes": {
      "title": "Post #1",
      "body": "Very big text"
    }
  }
}

Тут и возникает ситуация, что (при переходе из posts в post) хук model, который как раз используется для запроса на «/posts/**», будет проигнорирован и модель останется с пустым body.

«Заставить» Ember вызвать этот хук не получится. Лучше воспользоваться другими средствами. Например, хуком afterModel, который вызывается сразу после model и параметром принимает уже загруженную модель. А зачем нам неполная («недозагруженная») модель? Восполним недостающие данные через метод reload(#):

// app/routes/posts/post.js
import Ember from 'ember';
 
export default Ember.Route.extend({
 
  model(params) {
    return this.store.findRecord('post', params.post_id);
  },
 
  afterModel(model) {
     return model.reload();
  }
 
});

Сейчас перезагрузка модели происходит каждый раз при срабатывании хука afterModel. Можно добавить проверку на отсутствие каких-то данных (того же body) и выполнять reload только по надобности. Главное, не забыть, что результат reload’а (Promise) надо вернуть из хука.

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

, , , ,

Оставить комментарий

Top ↑ | Main page | Back