Nettoyer le chemin dans GWT / Java pour attendre la fin de plusieurs événements asynchrones



Answers

Comme @Epsen dit, Future est probablement ce que vous voulez. Malheureusement, je ne crois pas que Future soit compatible avec GWT. Le projet gwt-async-future prétend apporter cette fonctionnalité à GWT, même si je ne l'ai jamais essayé. Cela peut valoir le coup d'oeil.

Question

Quel est le meilleur moyen d'attendre que plusieurs fonctions de rappel asynchrones se terminent en Java avant de continuer? Plus précisément, j'utilise GWT avec AsyncCallback, mais je pense que c'est un problème générique. Voici ce que j'ai maintenant, mais sûrement il y a une manière plus propre ...

    AjaxLoader.loadApi("books", "0", new Runnable(){
        public void run() {
            bookAPIAvailable = true;
            ready();
        }}, null);
    AjaxLoader.loadApi("search", "1", new Runnable(){
        public void run() {
            searchAPIAvailable = true;
            ready();
        }}, null);


    loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
        public void onSuccess(LoginInfo result) {
            appLoaded  = true;
            ready();
        }
    });

private void ready() {
    if(bookAPIAvailable && searchAPIAvailable && appLoaded) {
                // Everything loaded
    }
}



Idéalement, vous voulez faire comme d'autres affiches ont déclaré et faire autant que vous le pouvez en un seul appel asynchrone. Parfois, vous devez faire un tas d'appels distincts. Voici comment:

Vous voulez enchaîner les appels asynchrones. Lorsque le dernier async est terminé (connexion), tous les éléments sont chargés.

    final AsyncCallback<LoginInfo> loginCallback = new AsyncCallback<LoginInfo>() {
        public void onSuccess(LoginInfo result) {
            //Everything loaded
            doSomethingNow();
        }
    };
    final Runnable searchRunnable = new Runnable() {
        public void run() {
            loginService.login(GWT.getHostPageBaseURL(), loginCallback);
        }
    };

    final Runnable booksRunnable = new Runnable() {
        public void run() {
            AjaxLoader.loadApi("search", "1", searchRunnable, null);
        }
    };

    //Kick off the chain of events
    AjaxLoader.loadApi("books", "0", booksRunnable, null);

À votre santé,

--Russ




J'ai fait quelque chose de similaire à @Sasquatch, mais en utilisant un objet "CallbackCounter":

public class CallbackCounter {
    private int outstanding;
    private final Callback<String, String> callback;
    private final String message;

    public CallbackCounter(int outstanding, Callback<String, String> callback, String callbackMessage) {
        this.outstanding = outstanding;
        this.callback = callback;
        this.message = callbackMessage;
    }

    public void count() {
        if (--outstanding <= 0) {
            callback.onSuccess(message);
        }
    }
}

Ensuite, dans mon rappel, je viens d'appeler:

counter.count();



Tout d'abord, ne vous mettez jamais dans une telle situation. Redessinez vos services RPC de sorte que chaque flux / écran utilisateur nécessite au plus un seul appel RPC pour fonctionner. Dans ce cas, vous faites trois appels au serveur, et c'est juste une perte de bande passante. La latence va simplement tuer votre application.

Si vous ne pouvez pas et avez vraiment besoin d'un hack, utilisez un Timer pour interroger périodiquement si toutes les données ont été téléchargées. Le code que vous avez collé ci-dessus suppose que la méthode login () sera la dernière à finir - ce qui est faux. C'est peut-être le premier à finir, et votre application sera dans un état indéterminé - ce qui est très difficile à déboguer.




Links