Как вернуть данные на основе обещания

У меня есть «виртуальный атрибут» в модели, и я хочу, чтобы установщик дождался обещания, прежде чем возвращать значение:

idShop:Ember.computed('shop',function(){
    get(key){
      return this.get('shop').id;
    },
    set(k,v){
      this.get('store').findRecord('shop',key)
      .then(shop =>{ 
        this.set('shop', shop)
      })
    }
  })

В наборе мне нужно вернуть либо k (ключ), либо shop.id после того, как findRecord и его then решены. Как я могу это сделать?

вы пробовали использовать шаблон async / await?

ashraf 26.07.2018 17:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
214
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Так что это отличный вариант использования Ember Concurrency.

Параллелизм Ember (EC) использует функции генератора function * () {} внутри своего метода task(), чтобы упростить управление такими вещами. Задача также предоставляет несколько служебных свойств, чтобы показать, является ли он в настоящее время running или idle (также известный как загрузка данных или загрузка данных завершена).

Вот как я это настроил (код для ember 2.17 и новее)

import {task} from 'ember-concurrency';
import {computed} from '@ember/object';
# skip ahead to later in the code...
shop: null,
loadShop: task(function*(key) {
   let shop = yield this.get('store').findRecord('shop', key)
   this.set('shop', shop)
}),
shopId: computed('shop', function() {
  if (this.get('shop') {
    return this.get('shop.id);
  } else {
     return null;
  }
})

В зависимости от вашего конкретного варианта использования вы должны вызвать this.get('loadShop').perform(id), когда знаете, какой будет идентификатор (вероятно, в ловушке инициализации или в отдельном методе)

(Примечание: это плохая практика изменять свойства как часть вычисляемого свойства. Вычисляемые свойства действительно не должны иметь состояния.)

Ответ принят как подходящий

С точки зрения дизайна это большой красный флаг. Я бы не стал использовать сеттер в этом случае, потому что он зависит от выполнения асинхронной задачи. Я вижу два варианта:

  1. перепроектировать вычисляемое свойство для использования объектов PromiseProxyMixin. (Это сильно усложнило бы ситуацию, и я бы не рекомендовал в этом случае)
  2. Откажитесь от использования сеттера сразу. Сделайте свойство readOnly и добавьте вызываемый вами метод для его установки, который может возвращать обещание.

Было бы легче рассуждать, если бы вы отправили модель в это свойство вместо ключа. Если это проблема из-за того, что вы придерживаетесь помощника по вводу с двусторонней привязкой, посмотрите версию этого селектора DDAU, чтобы он вызывал действие, а не устанавливал свойство. Или оберните это в компонент, который знает, как преобразовать ключ в модель, а затем установить модель в связи после ее разрешения.

Я думаю, что @ donald-wasserman предлагал последнее в своем примере тлеющий параллелизм. Однако в вашем случае это не обязательно. Это дало бы некоторые преимущества (отмена), но я бы не увлекся частью решения, связанной с параллелизмом, а только дизайном того, как и где вы выполняете асинхронный поиск.

Об асинхронных зависимостях гораздо легче рассуждать, когда они выполняются как действие, а не как побочные эффекты вычисляемых свойств. CP на самом деле не предназначены для асинхронных вещей. Я знаю, что в некоторых случаях это может сойти с рук, используя прокси (например, ember-data), но он вводит уровень когнитивной нагрузки, который может быстро выйти из-под контроля. По умолчанию используются действия для асинхронных нужд.

Для ванильного выбора у вас должен быть слой перевода (следовательно, компонент), который может преобразовывать строковый ключ в поиск модели. Некоторые избранные надстройки сделают это за вас (например, уголь-сила-выбор). За перевод поиска отвечает компонент, а не модель, поэтому, вероятно, вы столкнулись с трудностями.

Что касается добавления метода к модели для выполнения асинхронного поиска: вы можете это сделать, но я бы сказал, что это, вероятно, плохой выбор дизайна, поскольку он смешивает / размывает линию ответственности. (т.е. Принцип единственной ответственности S.O.L.I.D.)

Другими словами, потребности избранного - это проблема презентации. Тот факт, что существует необходимость преобразовать строку (для логики представления) в модель (для бизнес-логики), на самом деле не является обязанностью модели. Модель должна просто хранить отношения. Это компонент, который отображает выборку, которая отвечает за преобразование моделей в формат, подходящий для целей отображения, и обратно.

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