Use Ember.PromiseProxyMixin em um tema

Recentemente, o Ember.PromiseProxyMixin foi adicionado aos módulos do ember no núcleo do Discourse.

É um mixin do Ember muito útil que permite fazer solicitações assíncronas e trabalhar facilmente com Promises dentro de componentes do Ember. Pense nele como o React Suspense, mas para o Ember. O potencial é enorme para o desenvolvimento de temas e plugins no Discourse.

Aqui está a documentação oficial do Ember para o Ember.PromiseProxyMixin.

E aqui você pode encontrar um exemplo detalhado, fora do contexto do Discourse, de como usar o Ember.PromiseProxyMixin.

Vou dar um exemplo simples de como esse mixin pode ser usado dentro de um tema do Discourse. Digamos que, por algum motivo, no componente topic-list-item, você queira estilizar o avatar do poster se ele for membro da equipe; o avatar precisará ter uma borda diferente.

Em algum lugar do topic-list-item.js(.es6), você terá que:

  • Importar EmberObject e PromiseProxyMixin e estender o EmberObject com o PromiseProxyMixin
import EmberObject from "@ember/object";
import PromiseProxyMixin from "@ember/object/promise-proxy-mixin";

const PromiseObject = EmberObject.extend(PromiseProxyMixin);

// Você pode usar uma função de memoização personalizada para evitar múltiplas solicitações para o mesmo usuário
const getUser = memoize(username => ajax(`/u/${username}`).then(data => data));
  • Em seguida, você terá que criar essas propriedades computadas
  // Promise Computada
  @discourseComputed("topic")
  posterPromise(topic) {
    const { user } = topic.posters[0];
    return getUser(user.username);
  },

 // Essa CP envolve a promise com `PromiseObject`
  @discourseComputed("posterPromise")
  posterProxy() {
    const promise = this.get("posterPromise");
    return promise && PromiseObject.create({ promise });
  },

  posterData: reads("posterProxy.content.user"),

  @discourseComputed("posterData")
  isStaff() {
    const posterData = this.get("posterData");
    if (!posterData) return false;
    const { groups = [] } = posterData;
    // Para verificar se o usuário é membro da equipe, precisamos verificar
    // se o usuário pertence a um grupo de equipe
    return groups.some(({ name }) => name === "staff");
  }

E no template topic-list-item.hb(r|s), você teria algo assim:

  {{#if posterProxy.isFulfilled}}
    {{#if isStaff}}
      // faça sua customização
    {{/if}}
  {{/if}}

Você pode utilizar isPending para mostrar um loader, talvez.

Espero que este exemplo, que não é tão útil, possa ajudá-lo a entender como o mixin funciona e talvez ajude você a encontrar uma maneira de usá-lo no desenvolvimento do seu tema/plugin.

:wave:

4 curtidas

Olá @zcuric,

obrigado por este excelente resumo e pelo PR inicial. Com certeza há coisas a explorar aqui, tanto em plugins/temas quanto no código base do Discourse. Vamos ver como aplicar esse padrão e talvez torná-lo mais simples no futuro :+1:

5 curtidas