Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

O que Window[name] faz?

Alguém poderia me explica como o window[name] funciona, eu estava procurando uma maneira de fazer uma espécie de api fetch para JSONP, achei um código no github que eu adaptei para trabalhar com promise, na primeira chamada do método ele funcionou como o esperado, porem na segunda vez que ele é chamado dá um erro dizendo que a função callback is not define, e eu não entendi o por que desse erro. então resumindo a duvida é a seguinte, o que o window[name] faz e pq q meu código da erro na segunda execução.

class JsonpFetch {
  get(url, callback, name) {
    return new Promise((resolve, reject) => {
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.src = url;
      // Setup handler
      window[name] = function(data) {
        console.log(window);
        callback.call(window, data);
        document.getElementsByTagName("head")[0].removeChild(script);
        script = null;
        delete window[name];
        resolve(data);
      };
      // Load JSON
      document.getElementsByTagName("head")[0].appendChild(script);
    });
  }
}
10 respostas

Oi Flavio, tudo bem? No geral o window[name] não tá fazendo nada muito especial. Está só criando uma referência global para a sua função que irá executar.

Por que ela dá erro na segunda execução ai eu já não sei ser específico. Você pode mostrar pra mim como está usando?

posso é da seguinte maneira eu tenho um arquivo index.js que é carregado com a pagina, ai nele eu faço isso: let vitrineController = new VitrineController();

Arquivo VitrineController .js
==========================================
class VitrineController {
  /**
   * Contrutor, aqui está sendo definida as propriedades que fão parte desta classe.
   */
  constructor() {
    let $ = document.querySelector.bind(document);
    this._VitrineView = new VitrineReferenceView($("#reference-container"));
    this._vitrineDao = new VitrineDao();
    this._listRecommendation = new Bind(
      new ListRecommendation(),
      new VitrineRecommendationView($("#slider-inner")),
      "add",
      "addAll",
      "clean"
    );
    this._init();
  }

  /** 
Método de inicialização responsavel pela chamada dos demais metodos
*/
  _init() {
    this._vitrineNext();
    this._vitrineBack();
    this._listRecommendations();
    this._showReference();
  }
  //Este metodo carrega as informações vindas do dao e as exibe na view de referencia.
  _showReference() {
    let reference = this._vitrineDao
      .referenceItem()
      .then(e => this._VitrineView.update(e))
      .catch(e => console.log(e));
  }
  //Este metodo carrega as recomendações, e atrvés do databind exibe os itens recomendados em uma view especifica.
  _listRecommendations() {
    this._vitrineDao
      .listRecommendation()
      .then(recommendations => {
        console.log(recommendations);
        this._listRecommendation.addAll(recommendations);
      })
      .catch(e => console.log(e));
  }}
=========================================


Arquivo VitrineDao .js
=========================================
class VitrineDao {
  /**
   * Fornece um objeto de Reference com base no JSON recebido da função X
   * Retorna uma Reference
   */
  referenceItem() {
    return JsonpFetch.get(
      "http://linkextero.com/challenge.json?callback=X",
      x => x,
      "X"
    ).then(dataObject => {
      let item = dataObject.data.reference.item;
      return new Reference(
        item.businessId,
        item.detailUrl,
        item.imageName,
        item.name,
        item.oldPrice,
        item.price,
        item.productInfo.paymentConditions
      );
    });
  }
  /**
   * Processas as Recommendations recebidas da função X, motando um objeto de Recommendation adicionando-os em uma lista.
   * Retorna um array de Recommendations
   */
  listRecommendation() {
    return JsonpFetch.get(
      "http://linkextero.com/challenge.json?callback=X",
      x => x,
      "X"
    ).then(dataObject => {
      let recommendations = dataObject.data.recommendation;
      let listRecommendations = [];
      recommendations.forEach(recommendation => {
        listRecommendations.push(this._createRecommendation(recommendation));
      });
      return listRecommendations;
    });
  }
  /**
   *Recebe uma RecommendationData, objeto advindo da função X, o converte para um objeto Recommendation.
   * @param {*} recommendationData
   * Retorna uma Recommendation
   */
  _createRecommendation(recommendationData) {
    return new Recommendation(
      recommendationData.businessId,
      recommendationData.detailUrl,
      recommendationData.imageName,
      recommendationData.name,
      recommendationData.oldPrice,
      recommendationData.price,
      recommendationData.productInfo.paymentConditions
    );
  }
}

Certo, mas você disse dar erro na segunda execução, não é isso? Qual é a mensagem do erro em si, eu desconfio qual seja, mas queria ter certeza pra poder ser exato na explicação.

O erro é: ReferenceError: X is not defined

solução!

Flavio, olhando aqui eu só consegui imaginar um tipo de problema. Como você está trabalhando com Promise e requisições, quando você usa o parâmetro name, você tá sempre usando o mesmo valor X, o que pode acontecer?

Como o Window é um objeto e você está criando propriedades e deletando propriedades dele, usando o mesmo nome X, uma função pode acabar deletando a propriedade que outra função estava usando. Como isso tudo tá assíncrono, você não tem controle exato de quem vai terminar primeiro.

Meu chute pra resolver é: usa valores diferentes para o parâmetro name. Vê se resolve?

Foi o que eu suspeitei desde o principio.

A solução funcionou?

infelizmente não resolve pq não posso trocar o valor de name, se não a função x do JSONP não é executada, aceitei que essa chamada simplesmente não pode ser feita desse jeito que eu queria. mas a sua resposta ajudou bastante vlw :).

Flavio, uma solução é encadear as chamadas para que as promises sejam executadas uma após a outra, talvez isso ajude e resolve o problema. Como uma promise vai esperar pela outra, não deve gerar esse problema.