APIs e Microsserviços

19 mai, 2016

Crie um carregador básico com JavaScript Promises

Publicidade

Eu usei carregadores (loaders) JavaScript durante anos; ou era o carregador de Dojo, ou curl.js, ou mesmo usando jQuery como um carregador de JavaScript, que é extremamente útil para solicitar um conjunto de recursos e agir depois que concluiu o carregamento. Cada carregador de JavaScript é cheio de recursos, eficiente, e faz um trabalho maravilhoso de preencher a API Promise que não existia no navegador quando o carregador é criado. O que se segue não é esse tipo de carregador.

Este carregador super simples permite o carregamento de imagem, CSS e arquivos JavaScript, usando a API Promise, e dispara um retorno de sucesso ou fracasso. Esse pequeno “carregador” (eu nem deveria chamá-lo assim) não:

  • fornece resultados de cache (embora isso seria fácil)
  • proporciona um módulo/objeto de retorno
  • faz chamadas AJAX (embora um preenchimento XHR-to-Promise esteja disponível, ou você pode usar fetch)
  • …ou qualquer outra coisa avançada

Aqui está o pequeno “carregador” em toda a sua glória:

var load = (function() {
  // Função que retorna uma função: https://davidwalsh.name/javascript-functions
  function _load(tag) {
    return function(url) {
      // Esta promise será usada por Promise.all para determinar o sucesso ou fracasso
      return new Promise(function(resolve, reject) {
        var element = document.createElement(tag);
        var parent = 'body';
        var attr = 'src';

        // Importante sucesso e erro para a promise
        element.onload = function() {
          resolve(url);
        };
        element.onerror = function() {
          reject(url);
        };

        // Necessário definir atributos diferentes dependendo do tipo de tag
        switch(tag) {
          case 'script':
            element.async = true;
            break;
          case 'link':
            element.type = 'text/css';
            element.rel = 'stylesheet';
            attr = 'href';
            parent = 'head';
        }

        // Injetar no documento para lançar o carregamento
        element[attr] = url;
        document[parent].appendChild(element);
      });
    };
  }
  
  return {
    css: _load('link'),
    js: _load('script'),
    img: _load('img')
  }
})();

// Uso: Carrega diferentes tipos de arquivo com um callback
Promise.all([
    load.js('lib/highlighter.js'), 
    load.js('lib/main.js'), 
    load.css('lib/highlighter.css'),
    load.img('images/logo.png')
  ]).then(function() {
    console.log('Everything has loaded!');
  }).catch(function() {
    console.log('Oh no, epic failure!');
  });

Um objeto load é criado com as funções js, css e img, que aceitam uma URL para carregar. Cada função retorna uma Promise e o evento onload ou onerror da tag do recurso aciona resolve ou reject para o promise. Promise.all recolhe os recursos a serem carregados e then dispara o carregamento bem-sucedido de todos os recursos e catch caso algum deles falhar.

Tenho que salientar que ele se destina a ser um carregador muito, muito simples; por favor, lembre-se dos comentários sobre como ele não tem os recursos avançados que os outros carregadores têm. Eu amo como a API Promise torna o gerenciamento assíncrono e de recursos de carregamento, assim como a API ServiceWorker e a API fetch. Faça um favor a si mesmo e confira essas APIs impressionantes!

***

David Walsh faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://davidwalsh.name/javascript-loader