Partilhar via


Programação assíncrona em Suplementos do Office

Importante

Este artigo aplica-se às APIs Comuns, o modelo da API JavaScript do Office que foi introduzido com o Office 2013. Essas APIs incluem recursos como interface de usuário, caixas de diálogo e configurações de cliente, que são comuns entre vários tipos de aplicativos do Office. Os suplementos do Outlook usam exclusivamente APIs comuns, especialmente o subconjunto de APIs expostos por meio do objetoCaixa de Correio.

Você só deve usar APIs comuns para cenários que não têm suporte por APIs específicas do aplicativo. Para saber quando usar APIs comuns em vez de APIs específicas do aplicativo, confira Entendendo a API de JavaScript do Office.

Por que a API de Suplementos do Office usa a programação assíncrona? O JavaScript é uma linguagem de thread único. Se um script invocar um processo síncrono de execução prolongada do cliente do Office, todos os scripts subsequentes serão bloqueados até que esse processo seja concluído. Ser assíncrono garante que os Suplementos do Office são reativos e rápidos.

Os nomes de todos os métodos assíncronos nas APIs Comuns terminam com "Assíncrona", como , Document.getSelectedDataAsyncBinding.getDataAsyncou Item.loadCustomPropertiesAsync métodos. Quando um método "Assíncrono" é chamado, é executado imediatamente. O resto do script continua enquanto a operação é concluída no lado do cliente. A função de chamada de retorno opcional que transmite a um método "Assíncrono" é executada assim que os dados ou a operação pedida estiverem prontos. Geralmente, isto ocorre rapidamente, mas pode haver um ligeiro atraso.

O diagrama seguinte mostra o fluxo de um método "Assíncrono" que lê os dados que o utilizador selecionou num documento. Quando a chamada "Assíncrona" é efetuada, o thread JavaScript é gratuito para efetuar qualquer processamento adicional do lado do cliente (embora nenhum seja apresentado no diagrama). Quando o método "Assíncrono" é devolvido, a chamada de retorno é retomada no thread. Em seguida, o suplemento pode aceder aos dados, fazer algo com o mesmo e apresentar o resultado. O padrão é o mesmo entre plataformas.

Diagrama a mostrar a interação de execução de comandos ao longo do tempo com o utilizador, a página do suplemento e o servidor da aplicação Web que aloja o suplemento.

Escrever a função de chamada de retorno para um método "Assíncrono"

A função de chamada de retorno que transmite como argumento de chamada de retorno para um método "Assíncrono" tem de declarar um único parâmetro. O runtime do suplemento utiliza esse parâmetro para fornecer acesso a um objeto AsyncResult para a função de chamada de retorno.

A função de chamada de retorno pode ser uma função anónima ou uma função nomeada. Uma função anônima é útil se você só for usar seu código uma vez - porque ele não possui um nome, você não pode referenciá-la em outra parte do seu código. Uma função nomeada é útil se você quiser reutilizar a função retorno de chamada para mais de um método "Async".

Escrever uma função de chamada de retorno anónima

A seguinte função de chamada de retorno anónima declara um único parâmetro denominado result para os dados devolvidos pelo cliente. Obtém e escreve esses dados a partir da propriedade AsyncResult.value quando a chamada de retorno é devolvida.

function (result) {
    write('Selected data: ' + result.value);
}

O exemplo seguinte mostra esta função de chamada de retorno anónima no contexto de uma chamada de método "Assíncrona" completa para o Document.getSelectedDataAsync(coercionType, callback) método .

  • O primeiro argumento coercionType , Office.CoercionType.Text, especifica para devolver os dados selecionados como uma cadeia de texto.

  • O segundo argumento de chamada de retorno é a função anónima transmitida inline para o método . Quando a função é executada, utiliza o parâmetro de resultado para aceder à value propriedade do AsyncResult objeto. Em seguida, apresenta os dados selecionados pelo utilizador no documento.

Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, 
    function (result) {
        write('Selected data: ' + result.value);
    }
});

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

Também pode utilizar o parâmetro da função de chamada de retorno para aceder a outras propriedades do AsyncResult objeto. Use a propriedade AsyncResult.status para determinar se a chamada teve êxito ou falhou. Se a chamada tiver falhado, utilize a propriedade AsyncResult.error para aceder a um objeto Erro para ajudar a decidir o que fazer.

Para obter mais informações sobre o getSelectedDataAsync método, consulte Ler e escrever dados na seleção ativa num documento ou folha de cálculo.

Escrever uma função de chamada de retorno com nome

Em alternativa, pode escrever uma função com nome e transmitir o respetivo nome para o parâmetro de chamada de retorno de um método "Assíncrono". Aqui, o exemplo anterior é reescrito para transmitir uma função denominada writeDataCallback parâmetro de chamada de retorno .

Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, 
    writeDataCallback);

// Callback to write the selected data to the add-in UI.
function writeDataCallback(result) {
    write('Selected data: ' + result.value);
}

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message;
}

Diferenças no que é devolvido à AsyncResult.value propriedade

As asyncContextpropriedades , statuse error do AsyncResult objeto devolvem os mesmos tipos de informações às funções de chamada de retorno transmitidas a todos os métodos "Assíncrono". No entanto, o que é devolvido à AsyncResult.value propriedade varia consoante a funcionalidade do método "Assíncrono".

Por exemplo, os addHandlerAsync métodos (dos objetos Binding, CustomXmlPart, Document, RoamingSettings e Settings ) são utilizados para adicionar funções de processador de eventos. A AsyncResult.value propriedade nessas funções de chamada de retorno devolve sempre indefinido, uma vez que não são acedidos dados ou objetos quando adiciona um processador de eventos.

Por outro lado, se chamar o Document.getSelectedDataAsync método , este devolve os dados que o utilizador selecionou no documento como a AsyncResult.value propriedade na chamada de retorno. Em alternativa, se chamar o método Bindings.getAllAsync , devolve uma matriz de todos os Binding objetos no documento.

Para obter uma descrição do que é devolvido à AsyncResult.value propriedade de um Async método, veja a callback secção do tópico de referência desse método.

Padrões de programação assíncrona

As APIs Comuns na API javaScript do Office suportam dois tipos de padrões de programação assíncrona.

  • Chamadas de retorno aninhadas
  • Promessas

Observação

Na versão atual da API javaScript do Office, o suporte incorporado para o padrão de promessas só funciona com código para enlaces em folhas de cálculo do Excel e Word documentos. No entanto, pode encapsular outras funções que têm chamadas de retorno dentro da sua própria função personalizada Promise-returning. Para obter mais informações, veja Moldar APIs Comuns em Funções que devolvem promessas.

Programação assíncrona usando funções aninhadas de retorno de chamada

Frequentemente, você precisa executar duas ou mais operações assíncronas para concluir uma tarefa. Para fazer isso, você pode aninhar uma chamada "Async" dentro de outra.

O exemplo de código a seguir aninha duas ou mais chamadas assíncronas.

  • Primeiro, o método Bindings.getByIdAsync é chamado para acessar uma associação no documento chamado "MyBinding". O AsyncResult objeto devolvido ao result parâmetro dessa chamada de retorno fornece acesso ao objeto de enlace especificado a AsyncResult.value partir da propriedade .
  • Em seguida, o objeto de enlace acedido a partir do primeiro result parâmetro é utilizado para chamar o método Binding.getDataAsync .
  • Por fim, o result2 parâmetro da chamada de retorno transmitido ao Binding.getDataAsync método é utilizado para apresentar os dados no enlace.
function readData() {
    Office.context.document.bindings.getByIdAsync("MyBinding", function (result) {
        result.value.getDataAsync({ coercionType: 'text' }, function (result2) {
            write(result2.value);
        });
    });
}

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

Este padrão básico de chamada de retorno aninhado pode ser utilizado para todos os métodos assíncronos nas APIs Comuns.

Programação assíncrona usando o padrão de promessas para acessar dados em associações

Em vez de transmitir uma função de chamada de retorno e aguardar que a função regresse antes de o script continuar, o padrão de programação promete imediatamente um Promise objeto que representa o resultado pretendido. No entanto, ao contrário da programação síncrona verdadeira, nos bastidores, o cumprimento do resultado prometido é efetivamente adiado até que o ambiente de runtime dos Suplementos do Office conclua o pedido. Um manipulador onError é fornecido para atender a situações em que a solicitação não pode ser cumprida.

As APIs Comuns fornecem a função Office.select para suportar o padrão de promessas ao trabalhar com objetos de enlace existentes. O objeto de promessa devolvido à Office.select função só suporta os quatro métodos diretamente acessíveis a partir do objeto Enlace .

O padrão de promessas para trabalhar com enlaces assume este formulário.

Office.select( selectorExpression,onError).BindingObjectAsyncMethod;

O parâmetro selectorExpression assume o formulário "bindings#bindingId", em que bindingId é o nome ( id) de um enlace que criou no documento ou folha de cálculo (utilizando um dos métodos "addFrom" da Bindings coleção: addFromNamedItemAsync, addFromPromptAsyncou addFromSelectionAsync). O selector de exemploExpressão de bindings#cities especifica que pretende aceder ao enlace com um ID de "cidades".

O parâmetro onError é uma função de processamento de erros que utiliza um único parâmetro do tipo AsyncResult. Isto é utilizado para aceder a um Error objeto se a select função não conseguir aceder ao enlace especificado. O exemplo a seguir mostra uma função de manipulador de erro básica que pode ser transmitida para o parâmetro onError.

function onError(result){
    const err = result.error;
    write(err.name + ": " + err.message);
}

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

Substitua o marcador de posição BindingObjectAsyncMethod por uma chamada para qualquer um dos quatro Binding métodos de objeto suportados pelo objeto promise: getDataAsync, setDataAsync, addHandlerAsyncou removeHandlerAsync. As chamadas para esses métodos não oferecem suporte a promessas adicionais. Nesse caso, tem de utilizar o padrão de função de chamada de retorno aninhada.

Depois de uma Binding promessa de objeto ser cumprida, pode ser reutilizada na chamada de método em cadeia como se fosse um enlace. Se for bem-sucedido, o runtime do suplemento não tentará cumprir a promessa de forma assíncrona. Se não for possível cumprir a Binding promessa do objeto, o runtime do suplemento tentará novamente aceder ao objeto de enlace da próxima vez que um dos seus métodos assíncronos for invocado.

O exemplo seguinte utiliza a select função para obter um enlace com o id "cities" da Bindings coleção e, em seguida, chama o método addHandlerAsync para adicionar um processador de eventos para o evento dataChanged do enlace.

function addBindingDataChangedEventHandler() {
    Office.select("bindings#cities", function onError(){/* error handling code */}).addHandlerAsync(Office.EventType.BindingDataChanged,
    function (eventArgs) {
        doSomethingWithBinding(eventArgs.binding);
    });
}

Importante

A Binding promessa de objeto devolvida pela Office.select função fornece acesso apenas aos quatro métodos do Binding objeto. Se precisar de aceder a qualquer um dos outros membros do Binding objeto, tem de utilizar a Document.bindings propriedade e Bindings.getByIdAsync os métodos ou Bindings.getAllAsync para obter o Binding objeto.

Transmitir parâmetros opcionais para métodos assíncronos

A sintaxe comum para todos os métodos "Assíncrono" segue este padrão.

asyncMethod(requiredParameters, [parâmetros opcionais],callbackFunction);

Todos os métodos assíncronos suportam parâmetros opcionais. Estes são transmitidos como um objeto JavaScript. O objeto que contém os parâmetros opcionais é uma coleção não ordenada de pares chave-valor. Pode criar o objeto que contém parâmetros opcionais inline ou ao criar um options objeto e transmiti-lo como o parâmetro de opções .

Transmitir parâmetros opcionais inline

Eis um exemplo do método Document.setSelectedDataAsync com parâmetros opcionais definidos inline. Os dois parâmetros opcionais, coercionType e asyncContext, são definidos como um objeto JavaScript anónimo.

Office.context.document.setSelectedDataAsync(
    "<html><body>hello world</body></html>",
    {coercionType: "html", asyncContext: 42},
    function(asyncResult) {
        write(asyncResult.status + " " + asyncResult.asyncContext);
    }
)

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

Transmitir parâmetros opcionais num objeto com nome

Em alternativa, pode criar um objeto com nome que especifica os parâmetros opcionais separadamente da chamada de método e, em seguida, transmitir o objeto como argumento de opções . O exemplo seguinte mostra uma forma de criar um options objeto, em parameter1que , value1e assim por diante, são marcadores de posição para os nomes e valores dos parâmetros reais.

const options = {
    parameter1: value1,
    parameter2: value2,
    ...
    parameterN: valueN
};

Que é semelhante ao exemplo a seguir quando usado para especificar os parâmetros ValueFormat e FilterType.

const options = {
    valueFormat: "unformatted",
    filterType: "all"
};

Eis outra forma de criar o options objeto.

const options = {};
options[parameter1] = value1;
options[parameter2] = value2;
...
options[parameterN] = valueN;

O que se assemelha ao exemplo seguinte quando utilizado para especificar os ValueFormat parâmetros e FilterType :

const options = {};
options["ValueFormat"] = "unformatted";
options["FilterType"] = "all";

O exemplo seguinte mostra como chamar o Document.setSelectedDataAsync método ao especificar parâmetros opcionais num options objeto.

const options = {
   coercionType: "html",
   asyncContext: 42
};

document.setSelectedDataAsync(
    "<html><body>hello world</body></html>",
    options,
    function(asyncResult) {
        write(asyncResult.status + " " + asyncResult.asyncContext);
    }
)

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

Em ambos os exemplos de parâmetros opcionais, o parâmetro de chamada de retorno é especificado como o último parâmetro (seguindo os parâmetros opcionais inline ou seguindo o objeto de argumento opções ). Em alternativa, pode especificar o parâmetro de chamada de retorno dentro do objeto JavaScript inline ou no options objeto . No entanto, pode transmitir o parâmetro de chamada de retorno em apenas uma localização: no options objeto (inline ou criado externamente) ou como o último parâmetro, mas não ambos.

Encapsular APIs Comuns em Promisefunções que devolvem

Os métodos da API Comum (e da API do Outlook) não devolvem Promessas. Por conseguinte, não pode utilizar a opção aguardar para colocar a execução em pausa até que a operação assíncrona seja concluída. Se precisar de await comportamento, encapsular a chamada de método numa Promise.

O padrão básico é criar um método assíncrono que devolve imediatamente um objeto Promise e resolve esse objeto Promise quando o método interno é concluído ou rejeita o objeto se o método falhar. Apresentamos um exemplo simples a seguir.

function getDocumentFilePath() {
    return new OfficeExtension.Promise(function (resolve, reject) {
        try {
            Office.context.document.getFilePropertiesAsync(function (asyncResult) {
                resolve(asyncResult.value.url);
            });
        }
        catch (error) {
            reject(WordMarkdownConversion.errorHandler(error));
        }
    })
}

Quando esta função precisa de ser aguardada, pode ser chamada com o await palavra-chave ou transmitida para uma then função.

Observação

Esta técnica é especialmente útil quando precisa de chamar uma API Comum dentro de uma chamada da run função num modelo de objeto específico da aplicação. Para obter um exemplo da função que está a getDocumentFilePath ser utilizada desta forma, veja o ficheiroHome.js no exemplo Word-Add-in-JavaScript-MDConversion.

Confira também