Partager via


Programmation asynchrone dans des compléments Office

Importante

Cet article s’applique aux API communes, le modèle d’API JavaScript Office qui a été introduit avec Office 2013. Ces API comprennent des fonctionnalités telles qu’une interface utilisateur, des boîtes de dialogue et des paramètres du client, qui sont communes à plusieurs types d’applications Office. Les compléments Outlook utilisent uniquement les API communes, notamment le sous-ensemble d’API exposées via l’objet Boîte aux lettres .

Vous devriez utiliser les API communes uniquement pour les scénarios qui ne sont pas pris en charge par les API spécifiques de l’application. Pour savoir quand utiliser les API communes au lieu des API propres aux applications, consultez Comprendre l’API JavaScript Office.

Pourquoi l’API de Compléments Office a-t-elle recours à la programmation asynchrone ? JavaScript est un langage monothread. Si un script appelle un processus synchrone de longue durée du client Office, tous les scripts suivants sont bloqués jusqu’à la fin de ce processus. Le fait d’être asynchrone garantit que les compléments Office sont réactifs et rapides.

Les noms de toutes les méthodes asynchrones dans les API communes se terminent par « Async », telles que les Document.getSelectedDataAsyncméthodes , Binding.getDataAsyncou Item.loadCustomPropertiesAsync . Lorsqu’une méthode « Async » est appelée, elle s’exécute immédiatement. Le reste du script continue tant que l’opération se termine côté client. La fonction de rappel facultative que vous passez à une méthode « Async » s’exécute dès que les données ou l’opération demandée sont prêtes. Cela se produit généralement rapidement, mais il peut y avoir un léger retard.

Le diagramme suivant montre le flux d’une méthode « Async » qui lit les données sélectionnées par l’utilisateur dans un document. Lorsque l’appel « Async » est effectué, le thread JavaScript est libre d’effectuer tout traitement supplémentaire côté client (même si aucun n’est indiqué dans le diagramme). Lorsque la méthode « Async » est retournée, le rappel reprend sur le thread. Le complément peut ensuite accéder aux données, faire quelque chose avec elles et afficher le résultat. Le modèle est le même entre les plateformes.

Diagramme montrant l’interaction de l’exécution de commande au fil du temps avec l’utilisateur, la page de complément et le serveur d’applications web qui héberge le complément.

Écrire la fonction de rappel pour une méthode « Async »

La fonction de rappel que vous passez comme argument de rappel à une méthode « Async » doit déclarer un seul paramètre. Le runtime de complément utilise ce paramètre pour fournir l’accès à un objet AsyncResult pour la fonction de rappel.

La fonction de rappel peut être une fonction anonyme ou une fonction nommée. Une fonction anonyme est utile si vous envisagez de n’utiliser son code qu’une fois : comme elle n’a pas de nom, vous ne pouvez pas y faire référence dans une autre partie du code. Une fonction nommée est utile si vous voulez réutiliser la fonction de rappel pour plusieurs méthodes « Async ».

Écrire une fonction de rappel anonyme

La fonction de rappel anonyme suivante déclare un seul paramètre nommé result pour les données retournées par le client. Il récupère et écrit ces données à partir de la propriété AsyncResult.value lorsque le rappel est retourné.

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

L’exemple suivant montre cette fonction de rappel anonyme dans le contexte d’un appel de méthode « Async » complet à la Document.getSelectedDataAsync(coercionType, callback) méthode .

  • Le premier argument coercionType , Office.CoercionType.Text, spécifie de renvoyer les données sélectionnées sous la forme d’une chaîne de texte.

  • Le deuxième argument de rappel est la fonction anonyme passée inline à la méthode . Lorsque la fonction s’exécute, elle utilise le paramètre result pour accéder à la value propriété de l’objet AsyncResult . Il affiche ensuite les données sélectionnées par l’utilisateur dans le document.

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; 
}

Vous pouvez également utiliser le paramètre de votre fonction de rappel pour accéder à d’autres propriétés de l’objet AsyncResult . Utilisez la propriété AsyncResult.status pour déterminer si l’appel a réussi ou échoué. Si votre appel a échoué, utilisez la propriété AsyncResult.error pour accéder à un objet Error afin de décider ce qu’il faut faire.

Pour plus d’informations sur la getSelectedDataAsync méthode, consultez Lire et écrire des données dans la sélection active dans un document ou une feuille de calcul.

Écrire une fonction de rappel nommée

Vous pouvez également écrire une fonction nommée et passer son nom au paramètre de rappel d’une méthode « Async ». Ici, l’exemple précédent est réécrit pour passer une fonction nommée writeDataCallback en tant que paramètre de rappel .

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;
}

Différences dans ce qui est retourné à la AsyncResult.value propriété

Les asyncContextpropriétés , statuset error de l’objet AsyncResult retournent les mêmes types d’informations aux fonctions de rappel passées à toutes les méthodes « Async ». Toutefois, ce qui est retourné à la AsyncResult.value propriété varie en fonction des fonctionnalités de la méthode « Async ».

Par exemple, les addHandlerAsync méthodes (des objets Binding, CustomXmlPart, Document, RoamingSettings et Settings ) sont utilisées pour ajouter des fonctions de gestionnaire d’événements. La AsyncResult.value propriété dans ces fonctions de rappel retourne toujours undefined, car aucun objet ou donnée n’est accessible lorsque vous ajoutez un gestionnaire d’événements.

En revanche, si vous appelez la Document.getSelectedDataAsync méthode, elle retourne les données que l’utilisateur a sélectionnées dans le document en tant que AsyncResult.value propriété dans le rappel. Ou, si vous appelez la méthode Bindings.getAllAsync , elle retourne un tableau de tous les Binding objets du document.

Pour obtenir une description de ce qui est retourné à la AsyncResult.value propriété pour une Async méthode, consultez la section de la callback rubrique de référence de cette méthode.

Modèles de programmation asynchrone

Les API communes dans l’API JavaScript Office prennent en charge deux types de modèles de programmation asynchrone.

  • Rappels imbriqués
  • Promesses

Remarque

Dans la version actuelle de l’API JavaScript Office, la prise en charge intégrée du modèle promesses fonctionne uniquement avec le code pour les liaisons dans les feuilles de calcul Excel et les documents Word. Toutefois, vous pouvez encapsuler d’autres fonctions qui ont des rappels à l’intérieur de votre propre fonction de retour personnalisée Promise. Pour plus d’informations, consultez Wrapper les API courantes dans les fonctions de retour de promesses.

Programmation asynchrone utilisant des fonctions de rappel imbriquées

Vous devez fréquemment effectuer au moins deux opérations asynchrones pour réaliser une tâche. Pour ce faire, vous pouvez imbriquer un appel « Async » dans un autre.

L’exemple de code suivant imbrique deux appels asynchrones.

  • D’abord, la méthode Bindings.getByIdAsync est appelée pour accéder à une liaison dans le document nommé « MyBinding ». L’objet AsyncResult retourné au result paramètre de ce rappel fournit l’accès à l’objet de liaison spécifié à partir de la AsyncResult.value propriété .
  • Ensuite, l’objet de liaison accessible à partir du premier result paramètre est utilisé pour appeler la méthode Binding.getDataAsync .
  • Enfin, le result2 paramètre du rappel passé à la Binding.getDataAsync méthode est utilisé pour afficher les données dans la liaison.
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; 
}

Ce modèle de rappel imbriqué de base peut être utilisé pour toutes les méthodes asynchrones dans les API communes.

Programmation asynchrone en utilisant le modèle des promesses pour accéder aux données des liaisons

Au lieu de passer une fonction de rappel et d’attendre que la fonction retourne avant la poursuite du script, le modèle de programmation promise renvoie immédiatement un Promise objet qui représente son résultat prévu. Toutefois, contrairement à la programmation synchrone réelle, sous la couverture, l’exécution du résultat promis est en fait différée jusqu’à ce que l’environnement d’exécution des compléments Office termine la demande. Un gestionnaire onError est fourni pour couvrir les cas où la demande ne peut pas être remplie.

Les API communes fournissent la fonction Office.select pour prendre en charge le modèle de promesses lors de l’utilisation d’objets de liaison existants. L’objet promise retourné à la Office.select fonction prend uniquement en charge les quatre méthodes directement accessibles à partir de l’objet Binding .

Le modèle promesses pour l’utilisation des liaisons prend cette forme.

Office.select( selectorExpression,onError).BindingObjectAsyncMethod;

Le paramètre selectorExpression prend la forme "bindings#bindingId", où bindingId est le nom ( id) d’une liaison que vous avez créée dans le document ou la feuille de calcul (à l’aide de l’une des méthodes « addFrom » de la Bindings collection : addFromNamedItemAsync, addFromPromptAsyncou addFromSelectionAsync). L’exemple de sélecteurExpression de bindings#cities spécifie que vous souhaitez accéder à la liaison avec l’ID « cities ».

Le paramètre onError est une fonction de gestion des erreurs qui accepte un seul paramètre de type AsyncResult. Il est utilisé pour accéder à un Error objet si la select fonction ne parvient pas à accéder à la liaison spécifiée. L’exemple suivant montre une fonction de gestion des erreurs de base pouvant être passée au paramètre 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; 
}

Remplacez l’espace réservé BindingObjectAsyncMethod par un appel à l’une des quatre Binding méthodes d’objet prises en charge par l’objet promise : getDataAsync, setDataAsync, addHandlerAsyncou removeHandlerAsync. Les appels à ces méthodes ne prennent pas en charge les promesses supplémentaires. Dans ce cas, vous devez utiliser le modèle de fonction de rappel imbriqué.

Une fois qu’une promesse d’objet Binding est remplie, elle peut être réutilisée dans l’appel de méthode chaînée comme s’il s’agissait d’une liaison. Si l’opération réussit, le runtime du complément ne retentera pas la promesse de manière asynchrone. Si la Binding promesse d’objet ne peut pas être remplie, le runtime du complément réessayera d’accéder à l’objet de liaison la prochaine fois qu’une de ses méthodes asynchrones sera appelée.

L’exemple suivant utilise la select fonction pour récupérer une liaison avec le id «cities » de la Bindings collection, puis appelle la méthode addHandlerAsync pour ajouter un gestionnaire d’événements pour l’événement dataChanged de la liaison.

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

Importante

La Binding promesse d’objet retournée par la Office.select fonction fournit uniquement l’accès aux quatre méthodes de l’objet Binding . Si vous avez besoin d’accéder à l’un des autres membres de l’objet Binding , vous devez utiliser la Document.bindings propriété et Bindings.getByIdAsync les méthodes ou Bindings.getAllAsync pour récupérer l’objet Binding .

Passer des paramètres facultatifs aux méthodes asynchrones

La syntaxe commune de toutes les méthodes « Async » suit ce modèle.

asyncMethod(requiredParameters, [optionalParameters],callbackFunction);

Toutes les méthodes asynchrones prennent en charge les paramètres facultatifs. Ceux-ci sont transmis en tant qu’objet JavaScript. L’objet qui contient les paramètres facultatifs est une collection non triée de paires clé-valeur. Vous pouvez créer l’objet qui contient des paramètres facultatifs inline, ou en créant un options objet et en le transmettant en tant que paramètre options .

Passer des paramètres facultatifs inline

Voici un exemple de la méthode Document.setSelectedDataAsync avec des paramètres facultatifs définis inline. Les deux paramètres facultatifs, coercionType et asyncContext, sont définis en tant qu’objet JavaScript anonyme.

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; 
}

Passer des paramètres facultatifs dans un objet nommé

Vous pouvez également créer un objet nommé qui spécifie les paramètres facultatifs séparément de l’appel de méthode, puis passer l’objet comme argument options . L’exemple suivant montre une façon de créer un options objet, où parameter1, value1, et ainsi de suite, sont des espaces réservés pour les noms et valeurs de paramètres réels.

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

Ce qui ressemble à l’exemple suivant lors de la spécification des paramètres ValueFormat et FilterType.

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

Voici une autre façon de créer l’objet options .

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

Qui ressemble à l’exemple suivant lorsqu’il est utilisé pour spécifier les ValueFormat paramètres et FilterType :

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

L’exemple suivant montre comment appeler la Document.setSelectedDataAsync méthode en spécifiant des paramètres facultatifs dans un options objet .

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; 
}

Dans les deux exemples de paramètres facultatifs, le paramètre de rappel est spécifié comme dernier paramètre (suivant les paramètres facultatifs inline ou suivant l’objet d’argument options ). Vous pouvez également spécifier le paramètre de rappel à l’intérieur de l’objet JavaScript inline ou dans l’objet options . Toutefois, vous ne pouvez passer le paramètre de rappel qu’à un seul emplacement : soit dans l’objet options (inline ou créé en externe), soit en tant que dernier paramètre, mais pas les deux.

Encapsuler les API courantes dans Promiseles fonctions -returning

Les méthodes d’API commune (et d’API Outlook) ne retournent pas de promesses. Par conséquent, vous ne pouvez pas utiliser await pour suspendre l’exécution tant que l’opération asynchrone n’est pas terminée. Si vous avez besoin d’un await comportement, encapsulez l’appel de méthode dans un objet explicitement créé Promise.

Le modèle de base consiste à créer une méthode asynchrone qui retourne immédiatement un objet Promise et résout cet objet Promise lorsque la méthode interne se termine, ou rejette l’objet en cas d’échec de la méthode. Voici un exemple simple.

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));
        }
    })
}

Lorsque cette fonction doit être attendue, elle peut être appelée avec le await mot clé ou passée à une then fonction.

Remarque

Cette technique est particulièrement utile lorsque vous devez appeler une API commune à l’intérieur d’un appel de la run fonction dans un modèle objet spécifique à l’application. Pour obtenir un exemple de la getDocumentFilePath fonction utilisée de cette façon, consultez le fichier Home.js dans l’exemple Word-Add-in-JavaScript-MDConversion.

Voir aussi