WinJS no Windows 8.1

Crie aplicativos da Windows Store mais eficientes usando JavaScript: tratamento de erros

Eric Schmidt

Acredite ou não, às vezes os desenvolvedores de aplicativos escrevem códigos que não funcionam. Ou o código funciona, mas é terrivelmente ineficiente e trava a memória. Pior ainda, o código ineficiente resulta em um UX ruim, deixando os usuários loucos e obrigando-os a desinstalar o aplicativo e deixar críticas negativas.

Vou explorar os problemas comuns de desempenho e eficiência que podem surgir durante a criação de aplicativos para a Windows Store com JavaScript. Neste artigo, descreverei as práticas recomendadas de tratamento de erros usando a Biblioteca do Windows para JavaScript (WinJS). Em um artigo futuro, falarei sobre técnicas para fazer o trabalho sem bloquear o thread da interface de usuário, especificamente usando Trabalhos da Web ou a nova API WinJS.Utilities.Scheduler no WinJS 2.0, encontrada no Windows 8.1. Também vou apresentar o novo modelo de ciclo de vida de objeto previsível no WinJS 2.0, com foco particular em quando e como descartar os controles.

Para cada área de assunto, vou me concentrar em três coisas:

  • Erros ou ineficiências que podem surgir em um aplicativo para a Windows Store criado usando o JavaScript.
  • Ferramentas de diagnóstico para encontrar esses erros e ineficiências.
  • APIs, recursos e práticas recomendadas do WinJS que possam amenizar problemas específicos.

Eu forneço um código propositadamente com bug, mas fique tranquilo, eu indico no código que algo pode ou não funcionar.

Eu uso o Visual Studio 2013, o Windows 8.1 e o WinJS 2.0 para essas demonstrações. Muitas das ferramentas de diagnóstico que eu uso são fornecidas no Visual Studio 2013. Se você ainda não baixou as versões mais recentes das ferramentas, você pode obtê-las no Centro de Desenvolvimento do Windows (bit.ly/K8nkk1). Novas ferramentas de diagnóstico são lançadas por meio de atualizações do Visual Studio, por isso, verifique se há atualizações periodicamente.

Presumo uma familiaridade significativa com a criação de aplicativos para a Windows Store usando JavaScript. Se você for relativamente novo na plataforma, sugiro começar com o exemplo básico “Olá, mundo” (bit.ly/vVbVHC) ou, para aumentar o desafio, a amostra do Hilo para JavaScript (bit.ly/SgI0AA).

Configurando o exemplo

Primeiramente, crio um novo projeto no Visual Studio 2013 usando o modelo Navigation App (aplicativo de navegação), que oferece um bom ponto de partida para um aplicativo básico de várias páginas. Também adiciono um controle NavBar (bit.ly/14vfvih) à página default.html na raiz da solução, substituindo o código AppBar fornecido pelo modelo. Como quero demonstrar vários conceitos, ferramentas de diagnóstico e técnicas de programação, vou adicionar uma nova página ao aplicativo para cada demonstração. Com isso, fica muito mais fácil para eu navegar entre todos os casos de teste.

A marcação HTML completa para o NavBar é mostrada na Figura 1. Copie e cole este código em sua solução se você estiver seguindo o exemplo.

Figura 1 O controle NavBar

<!-- The global navigation bar for the app. -->
<div id="navBar" data-win-control="WinJS.UI.NavBar">
  <div id="navContainer" 
       data-win-control="WinJS.UI.NavBarContainer">
    <div id="homeNav" 
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/home/home.html',
        icon: 'home',
        label: 'Home page'
    }">
    </div>
    <div id="handlingErrors"
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/handlingErrors/handlingErrors.html',
        icon: 'help',
        label: 'Handling errors'
    }">
    </div>
    <div id="chainedAsync"
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/chainedAsync/chainedAsync.html',
        icon: 'link',
        label: 'Chained asynchronous calls'
    }">
    </div>
  </div>
</div>

Para obter mais informações sobre a criação de uma barra de navegação, confira algumas colunas sobre aplicativos modernos de Rachel Appel, como a publicada em msdn.microsoft.com/magazine/dn342878.

Você pode executar este projeto apenas com a barra de navegação, exceto que clicar em um dos botões de navegação irá gerar uma exceção em navigator.js. Mais adiante neste artigo, vou explicar como tratar os erros que surgem em navigator.js. Por enquanto, lembre-se de que o aplicativo começa sempre na página inicial e você precisa clicar com o botão direito no aplicativo para abrir a barra de navegação.

Tratamento de erros

Obviamente, a melhor maneira de evitar erros é lançar aplicativos que não apresentem erros. Em um mundo perfeito, todo desenvolvedor deve escrever o código perfeito para nunca falhar nem gerar uma exceção. Esse mundo perfeito não existe.

Por mais que os usuários prefiram aplicativos que sejam completamente livres de erros, eles são excepcionalmente bons em encontrar maneiras novas e criativas de corromper aplicativos de maneiras que você nunca sonhou. Por isso, você precisa incorporar um tratamento de erros robusto em seus aplicativos.

Os erros de aplicativos criados com JavaScript e HTML para a Windows Store têm o mesmo efeito dos erros de páginas normais da Web. Quando ocorre um erro em um objeto DOM (Document Object Model) que permite o tratamento de erros (por exemplo: elementos <script>, <style> ou <img>), o evento onerror para esse elemento é gerado. Para erros na pilha de chamadas JavaScript, o erro viaja até a cadeia de chamadas de ser pego (em um bloco try/catch, por exemplo) ou até atingir o objeto de janela, gerando o evento window.onerror.

O WinJS fornece várias camadas de oportunidades de tratamento de erros para seu código além do que já é fornecido para as páginas normais da Web pela Microsoft Web Platform. Em um nível fundamental, qualquer erro não pego em um bloco try/catch ou no manipulador onError aplicado a um objeto WinJS.Promise (em uma chamada para os métodos then ou done, por exemplo) gera o evento WinJS.Application.onerror. Examinarei isso em breve.

Na prática, você pode ouvir por erros em outros níveis além de Application.onerror. Com o WinJS e os modelos fornecidos pelo Visual Studio, você também pode tratar erros no nível de controle de página e no nível de navegação. Quando um erro é gerado enquanto o aplicativo estiver navegando para e carregando uma página, o erro aciona o tratamento de erros no nível da navegação, o tratamento de erros no nível da página e, finalmente, o tratamento de erros no nível do aplicativo. Você pode cancelar o erro no nível de navegação, mas os manipuladores de eventos aplicados ao manipulador de erros de página ainda serão gerados.

Neste artigo, passarei por cada camada de tratamento de erros, começando pelo mais importante: o evento Application.onerror.

Tratamento de erros no nível do aplicativo

O WinJS fornece o evento WinJS.Application.onerror (bit.ly/1cOctjC), a linha de defesa mais básica contra erros de seu aplicativo. Ele pega todos os erros capturados por window.onerror. Também pega promises que apresentam erros e os erros que ocorrem no processo de gerenciamento de eventos do modelo de aplicativo. Embora você possa aplicar um manipulador de eventos ao evento window.onerror em seu aplicativo, é bem melhor apenas usar Application.onerror para uma única fila de eventos a serem monitorados. 

Quando o manipulador Application.onerror pega um erro, você precisa decidir como solucioná-lo. Há várias opções:

  • Para erros de bloqueio críticos, alerte o usuário com uma caixa de diálogo de mensagem. Erro crítico é aquele que afeta a continuidade do funcionamento do aplicativo e pode exigir a intervenção do usuário para continuar.
  • Para erros de informação e não de bloqueio (como uma falha para sincronizar ou obter dados online), alerte o usuário com um submenu ou uma mensagem embutida.
  • Para erros que não afetam o UX, "engula" silenciosamente o erro.
  • Na maioria dos casos, grave o erro em um TraceLog (especialmente um que esteja ligado a um mecanismo de análise) para poder adquirir a telemetria do cliente. Para saber quais são os SDKs de análise disponíveis, visite o diretório de serviços do Windows em services.windowsstore.com e clique em Analytics (sob “By service type”) na lista à esquerda.

Para este exemplo, ficarei com caixas de diálogo de mensagem. Abro o default.js (/js/default.js) e adiciono o código mostrado em Figura 2 dentro da principal função anônima, abaixo do manipulador do evento app.oncheckpoint.

Figura 2 Adicionando uma caixa de diálogo de mensagem

app.onerror = function (err) {
  var message = err.detail.errorMessage ||
    (err.detail.exception && err.detail.exception.message) ||
    "Indeterminate error";
  if (Windows.UI.Popups.MessageDialog) {
    var messageDialog =
      new Windows.UI.Popups.MessageDialog(
        message,
        "Something bad happened ...");
    messageDialog.showAsync();
    return true;
  }
}

Neste exemplo, o manipulador de eventos de erro mostra uma mensagem informando ao usuário que ocorreu um erro e que erro é esse. O manipulador de eventos retorna true para manter a caixa de diálogo de mensagem aberta até que o usuário a descarte. (Retornar true também informa o processo WWAHost.exe que o erro foi tratado e pode continuar.)

Agora vou criar alguns erros para tratar neste código. Criarei um erro personalizado, lançarei o erro e depois o capturarei no manipulador de eventos. Para este primeiro exemplo, adiciono uma nova pasta chamada handling­Errors à pasta pages. Na pasta, adiciono um novo controle de página clicando com o botão direito no projeto no Gerenciador de Soluções e selecionando Add | New Item. Quando adiciono o controle de página handlingErrors ao meu projeto, o Visual Studio fornece três arquivos na pasta the handlingErrors (/pages/handlingErrors): handlingErrors.html, handling­Errors.js e handlingErrors.css.

Abro o handlingErrors.html e adiciono esta marcação simples dentro da marca <section> do corpo:

<!-- When clicked, this button raises a custom error. -->
<button id="throwError">Throw an error!</button>

Em seguida, abro o handlingErrors.js e adiciono um manipulador de eventos ao botão no método ready do objeto PageControl, conforme mostrado na Figura 3. Forneci a definição inteira de PageControl em handlingErrors.js para ilustrar o contexto.

Figura 3 Definição de PageControl em handlingErrors

// For an introduction to the Page Control template, see the following documentation:
// https://go.microsoft.com/fwlink/?LinkId=232511
(function () {
  "use strict";
  WinJS.UI.Pages.define("/pages/handlingErrors/handlingErrors.html", {
    ready: function (element, options) {
      // ERROR: This code raises a custom error.
      throwError.addEventListener("click", function () {
        var newError = new WinJS.ErrorFromName("Custom error", 
          "I'm an error!");
        throw newError;
      });
    },
    unload: function () {
      // Respond to navigations away from this page.
      },
    updateLayout: function (element) {
      // Respond to changes in layout.
    }
  });
})();

Agora pressiono F5 para executar a amostra, navego até a página handling­Errors e clico no botão “Throw an error!”. (Se você estiver acompanhando, verá uma caixa de diálogo do Visual Studio informando que um erro foi gerado. Clique em Continuar para manter a amostra em execução.) Em seguida, uma caixa de diálogo de mensagem surgirá com o erro, como ilustrado na Figura 4.

The Custom Error Displayed in a Message Dialog
Figura 4 Erro personalizado exibido em uma caixa de diálogo de mensagem

Erros personalizados

O evento Application.onerror tem algumas expectativas sobre os erros que ele trata. A melhor maneira de criar um erro personalizado é usar o objeto WinJS.ErrorFromName (bit.ly/1gDESJC). O objeto criado expõe uma interface padrão para os manipuladores de erro analisarem.

Para criar seu próprio erro personalizado sem usar o objeto ErrorFromName, você precisa implementar um método toString que retorna a mensagem de erro.

Caso contrário, quando seu erro personalizado é gerado, o depurador do Visual Studio e a caixa de diálogo de mensagem mostram "[object Object]". Cada um deles chama o método toString para o objeto, mas como esse método é definido no objeto imediato, ele passa pela cadeia de herança de protótipo para obter uma definição de toString. Ao atingir o tipo primitivo de objeto que tem um método toString, ele chama esse método (que apenas exibe informações sobre o objeto).

Tratamento de erros no nível da página

O objeto PageControl em WinJS fornece outra camada de manipulação de erro para um aplicativo. O WinJS chamará o método IPageControlMembers.error quando ocorrer um erro ao carregar a página. Depois que a página for carregada, no entanto, os erros do método IPageControlMembers.error são capturados pelo manipulador de eventos Application.onerror, ignorando o método de erro da página.

Adicionarei um método de erro ao PageControl que representa a página handleErrors. O método de erro agrava no console JavaScript do Visual Studio usando WinJS.log. A funcionalidade de registro em log precisa ser iniciada primeiro, então, preciso chamar WinJS.Utilities.startLog antes de tentar usar esse método. Observe também que eu verifico a existência do membro WinJS.log antes de eu realmente chamá-lo.

O código completo para handleErrors.js (/pages/handleErrors/handleErrors.js) é mostrado na Figura 5.

Figura 5 O handleErrors.js completo

(function () {
  "use strict";
  WinJS.UI.Pages.define("/pages/handlingErrors/handlingErrors.html", {
    ready: function (element, options) {
      // ERROR: This code raises a custom error.      
      throwError.addEventListener("click", function () {
        var newError = {
          message: "I'm an error!",
          toString: function () {
            return this.message;
          }
        };
        throw newError;
      })
    },
    error: function (err) {
      WinJS.Utilities.startLog({ type: "pageError", tags: "Page" });
      WinJS.log && WinJS.log(err.message, "Page", "pageError");
    },
    unload: function () {
      // TODO: Respond to navigations away from this page.
    },
    updateLayout: function (element) {
      // TODO: Respond to changes in layout.
    }
  });
})();

WinJS.log

A chamada para WinJS.Utilities.startLog mostrada na Figura 5 inicia a função auxiliar WinJS.log, que grava o resultado no console JavaScript por padrão. Embora isso seja muito útil no momento do design para a depuração, não permite que você capture dados de erros depois que os usuários instalam o aplicativo.

Para aplicativos que estão prontos publicação e implantação, você deve considerar a criação de sua própria implementação do WinJS.log que chame um mecanismo de análise. Isso permite que você colete dados de telemetria sobre o desempenho de seu aplicativo para poder corrigir bugs imprevistos em futuras versões do aplicativo. Apenas certifique-se de que os clientes estejam cientes da coleta de dados e que você liste claramente quais dados são coletados pelo mecanismo de análise na política de privacidade de seu aplicativo.

Observe que quando você substituir o WinJS.log dessa forma, a função WinJS.log capturará todos os resultados que, em outra situação, iriam para o console JavaScript, inclusive coisas como atualizações de status do Scheduler. É por isso que você precisa passar um nome e valor de tipo significativos na chamada para WinJS.Utilities.startLog para pode filtrar todos os erros indesejados.

Agora vou tentar executar a amostra e clicar em "Throw an error!" novamente. Isso resulta em um comportamento exatamente igual ao de antes: O Visual Studio captura o erro e o evento Application.onerror dispara. O console JavaScript não mostra mensagens relacionadas ao erro porque o erro foi gerado depois de a página ser carregada. Assim, o erro foi capturado somente pelo manipulador de eventos Application.onerror.

Então, por que usar o tratamento de erros PageControl? Bem, isso é particularmente útil para capturar e diagnosticar erros nos controles WinJS que são criados declaradamente no código HTML. Por exemplo, vou adicionar a seguinte marcação HTML dentro das marcas <section> de handleErrors.html (/pages/handleErrors/handleErrors.html), abaixo do botão:

<!-- ERROR: AppBarCommands must be button elements by default
  unless specified otherwise by the 'type' property. -->
<div data-win-control="WinJS.UI.AppBarCommand"></div>

Agora pressiono F5 para executar a amostra e navego até a página handleErrors. Mais uma vez, a caixa de diálogo de mensagem aparece até ser descartada. No entanto, a seguinte mensagem aparece no console JavaScript (você precisa voltar para a área de trabalho para verificar isso):

pageError: Page: Invalid argument: For a button, toggle, or flyout   command, the element must be null or a button element

Observe que o tratamento de erros no nível do aplicativo apareceu mesmo eu tratando o erro no PageControl (que registrou o erro em log). Então, como posso prender um erro em uma página sem que ele se estenda ao aplicativo?

A melhor maneira de prender um erro no nível da página é adicionar o tratamento de erros ao código de navegação. Demonstrarei isso a seguir.

Tratamento de erros no nível da navegação

Quando executei o teste anterior, onde o manipulador de eventos app.onerror tratou o erro do nível da página, o aplicativo parecia permanecer na página inicial. No entanto, por algum motivo, um controle do botão Voltar apareceu. Quando cliquei no botão Voltar, ele me levou para uma página handlingErrors.html (desativada).

Isso ocorre porque o código de navegação em navigator.js (/js/navigator.js), que é fornecido no modelo de projeto Navigation App, ainda tenta navegar para a página, mesmo ela tendo apresentado falha. Além disso, ele retorna à página inicial e adiciona a página propensa a erros ao histórico de navegação. É por isso que eu vejo no botão Voltar na página inicial depois de tentar navegar para handlingErrors.html.

Para cancelar o erro em navigator.js, substituo a função PageControl­Navigator._navigating pelo código na Figura 6. Você vê que a função de navegação contém uma chamada para WinJS.UI.Pages.render, que retorna um objeto Promise. O método render tenta criar um novo PageControl a partir da URI passado a ele e inseri-lo em um elemento host. Como o PageControl resultante contém um erro, o promise retornado apresenta erro. Para interceptar o erro gerado durante a navegação, adiciono um manipulador de erros ao parâmetro onError do método then exposto por esse objeto Promise. Isso intercepta efetivamente o erro, impedindo-a de gerar o evento Application.onerror.

Figura 6 A função PageControlNavigator._navigating em navigator.js

// Other PageControlNavigator code ...
// Responds to navigation by adding new pages to the DOM.
_navigating: function (args) {
  var newElement = this._createPageElement();
  this._element.appendChild(newElement);
  this._lastNavigationPromise.cancel();
  var that = this;
  this._lastNavigationPromise = WinJS.Promise.as().then(function () {
    return WinJS.UI.Pages.render(args.detail.location, newElement,
       args.detail.state);
  }).then(function parentElement(control) {
    var oldElement = that.pageElement;
    // Cleanup and remove previous element
    if (oldElement.winControl) {
      if (oldElement.winControl.unload) {
        oldElement.winControl.unload();
      }
      oldElement.winControl.dispose();
    }
    oldElement.parentNode.removeChild(oldElement);
    oldElement.innerText = "";
  },
  // Display any errors raised by a page control,
  // clear the backstack, and cancel the error.
  function (err) {
    var messageDialog =
      new Windows.UI.Popups.MessageDialog(
        err.message,
        "Sorry, can't navigate to that page.");
    messageDialog.showAsync()
    nav.history.backStack.pop();
    return true;
  });
  args.detail.setPromise(this._lastNavigationPromise);
},
// Other PageControlNavigator code ...

Promises do WinJS

A criação de promises e o encadeamento de promises – e as práticas recomendadas para isso – foram abordados em muitos outros lugares, então, vou pular essa parte neste artigo. Se você precisar de mais informações, leia a postagem no blog de Kraig Brockschmidt em bit.ly/1cgMAnu ou apêndice A do e-book gratuito dele, “Programming Windows Store Apps with HTML, CSS, and JavaScript, segunda edição” (bit.ly/1dZwW1k).

Observe que é perfeitamente adequado modificar navigator.js. Embora seja fornecido pelo modelo de projeto do Visual Studio, e faz parte do código de seu aplicativo e pode ser modificado como você precisar.

Na função _navigating, adicionei um manipulador de erros à chamada promise.then final. O manipulador de erros mostra uma caixa de diálogo de mensagem – como no tratamento de erros no nível do aplicativo – e depois cancela o erro retornando true. Ele também remove a página do histórico de navegação.

Quando executo a amostra novamente e navego para handlingErrors.html, vejo a caixa de diálogo de mensagem que me informa que a tentativa de navegação falhou. A caixa de diálogo de mensagem do tratamento de erros no nível do aplicativo não aparece.

Rastreamento de erros em cadeias assíncronas

Ao construir aplicativos em JavaScript, frequentemente preciso seguir executar uma tarefa assíncrona após a outra, e eu faço isso criando cadeias de promises. Os promises encadeados continuarão a se deslocar pelas tarefas, mesmo se um dos promises na cadeia retornar erro. A prática recomendada é sempre terminar uma cadeia de promises com uma chamada para o método done. A função done lança os erros que seriam pegos no manipulador de erros para todas as instruções then anteriores. Isso significa que não preciso definir funções de erro para cada promise em uma cadeia.

Mesmo assim, rastrear erros pode ser difícil em cadeias muito longas, pois eles são interceptados na chamada para promise.done. Promises encadeados podem incluir várias tarefas, e qualquer um deles pode falhar. Eu poderia definir um ponto de interrupção em cada tarefa para ver onde o erro aparece, mas isso seria terrivelmente demorado.

É aí que o Visual Studio 2013 entra. A janela Tarefas (introduzida no Visual Studio 2010) foi atualizada para lidar com a depuração assíncrona de JavaScript também. Na janela Tarefas, que você pode ver todas as tarefas ativas e concluídas em determinado ponto em seu código do aplicativo.

Para este próximo exemplo, vou adicionar uma nova página à solução de demonstrar essa ferramenta incrível. Na solução, crio uma nova pasta chamada chainedAsync na pasta pages e adiciono um novo controle de página chamado chainAsync.html (que cria /pages/chainedAsync/chainedAsync.html e arquivos .js e css associados).

Em chainedAsync.html, insiro a seguinte marcação dentro das marcas <section>:

<!-- ERROR:Clicking this button starts a chain reaction with an error. -->
<p><button id="startChain">Start the error chain</button></p>
<p id="output"></p>

Em chainedAsync.js, adiciono o manipulador de eventos mostrado na Figura 7 para o evento click do botão startChain ao método ready para a página.

Figura 7 O conteúdo da função PageControl.ready em chainedAsync.js

startChain.addEventListener("click", function () {
  goodPromise().
    then(function () {
        return goodPromise();
    }).
    then(function () {
        return badPromise();
    }).
    then(function () {
        return goodPromise();
    }).
    done(function () {
        // This *shouldn't* get called
    },
      function (err) {
          document.getElementById('output').innerText = err.toString();
    });
});

Por último, defino as funções goodPromise e badPromise, mostradas na Figura 8, dentro de chainAsync.js para que fiquem disponíveis nos métodos de PageControl.

Figura 8 As definições das funções goodPromise e badPromise em chainAsync.js

function goodPromise() {
  return new WinJS.Promise(function (comp, err, prog) {
    try {
      comp();
    } catch (ex) {
      err(ex)
    }
  });
}
// ERROR: This returns an errored-out promise.
function badPromise() {
  return WinJS.Promise.wrapError("I broke my promise :(");
}

Executo a amostra novamente, navego até a página “Chained asynchronous” e clico em “Start the error chain”. Após uma breve espera, a mensagem “I broke my promise :(” aparece embaixo do botão.

Agora preciso rastrear onde ocorreu esse erro e descobrir como corrigi-lo. (Obviamente, em uma situação simulada como esta, sei exatamente onde ocorreu o erro. Para fins de aprendizagem, vou esquecer que badPromise injetou o erro em meus promises encadeados.)

Para descobrir onde os promises encadeados dão errado, vou colocar um ponto de interrupção no manipulador de erros definido na chamada efetuada no manipulador de cliques para o botão startChain, como mostrado na Figura 9.

The Position of the Breakpoint in chainedAsync.html
Figura 9 A posição do ponto de interrupção em chainedAsync.html

Executo o mesmo teste novamente e, quando retorno ao Visual Studio, a execução do programa para no ponto de interrupção. Em seguida, abro a janela Tasks (Debug | Windows | Tasks) para ver quais as tarefas que estão ativas no momento. Os resultados são mostrados na Figura 10.

The Tasks Window in Visual Studio 2013 Showing the Error
Figura 10 A janela Tasks do Visual Studio 2013 mostrando o erro

Em primeiro lugar, nada nesta janela realmente se destaca como a causa do erro. A janela lista cinco tarefas, todas marcadas como ativas. Como olho mais de perto, no entanto, vejo que uma das tarefas ativas é o enfileiramento de erros de promise no Schedules – e isso parece promissor (desculpe o trocadilho ruim).

(Se você quiser saber mais sobre o Scheduler, recomendo a leitura do próximo artigo desta série, onde falarei sobre a nova API Scheduler do WinJS.)

Quando passo meu mouse por essa linha (ID 120 na Figura 10) na janela Tasks, recebo uma exibição segmentada da pilha de chamadas para essa tarefa. Vejo vários manipuladores de erros e, olhe só, badPromise está perto do início dessa pilha de chamadas. Quando eu clico duas vezes nessa linha, o Visual Studio me leva diretamente para a linha de código em badPromise que gerou o erro. No mundo real, agora eu diagnosticaria por que badPromise estava gerando um erro.

O WinJS fornece vários níveis de tratamento de erros em um aplicativo, acima e além do bloco try-catch-finally confiável. Um aplicativo com bom desempenho deve usar um grau adequado de tratamento de erros para proporcionar uma experiência positiva para os usuários. Neste artigo, demonstrei como incorporar o tratamento de erros nos níveis do aplicativo, da página e da navegação em um aplicativo. Também demonstrei como usar algumas das novas ferramentas do Visual Studio 2013 para rastrear erros em promises encadeados.

No próximo artigo desta série, vou explorar algumas técnicas para melhorar o desempenho de aplicativos da Windows Store. Examinarei trabalhos da Web, a nova API Scheduler do WinJS 2.0 e o novo padrão de descarte no WinJS 2.0.

Eric Schmidt é desenvolvedor de conteúdo na equipe de Conteúdo para desenvolvedores do Windows da Microsoft, escrevendo sobre a Biblioteca do Windows para JavaScript (WinJS). Anteriormente, ele trabalhou na divisão do Microsoft Office, onde criou amostras de código para a plataforma Apps for Office. Ele passa seu tempo com a família, toca contrabaixo, cria videogames em HTML5 e posta em blog sobre brinquedos de montar de plástico (historybricks.com).

AGRADECEMOS aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: Kraig Brockschmidt e Josh Williams
Kraig Brockschmidt é um gerente de programa sênior da equipe de Ecossistema do Windows, trabalhando diretamente com a comunidade de desenvolvedores e parceiros-chave na criação de aplicativos para a Windows Store. Ele é autor do livro Programming Windows Store Apps in HTML, CSS, and JavaScript (já em sua segunda edição) e compartilha outros conhecimentos em http://www.kraigbrockschmidt.com/blog.

Josh Williams é engenheiro-chefe de desenvolvimento de software da equipe de Experiência de Desenvolvedor do Windows. Ele e sua equipe criaram a Biblioteca do Windows para JavaScript (WinJS).