Combinazione di programmazione asincrona e sincrona

3

Ho dei problemi che mi avvolgono attorno a un certo problema:

Nella mia app di flusso di dati (un editor visuale), ho entrambi gli oggetti autonomi che comunicano attraverso le porte tramite messaggi simultanei non ordinati e rappresentano quindi un sistema asincrono.

Ancora,voglioancheusarefunzionichesonosincrone,peresempiohannobisognodiinputpercalcolarneilvalore

Orailproblemaè:comepossocombinareentrambiconunsistemanonbanale?

In questa immagine, f ha bisogno di xey per calcolare il suo valore, ma in qualsiasi momento, può essere presente solo un input (supponiamo che x sia presente, y non lo sia). Generalizza questo alle dimensioni superiori

Vedo una possibile via d'uscita:

  • crea x un array X = (x, y) e combina i primi due oggetti risultanti in un sistema di tipo 1 ..

  • o crea un oggetto attivo, che memorizza in cache x, y e poi calcola

  • o make f calcola sempre il suo valore (ad esempio quando è presente solo x, calcola x * y = x * 0 ...)

Quindi è stata menzionata la possibilità di futures. Sto usando Java, quindi inquadrerò la mia possibile soluzione tramite Oggetti

Xvieneinviato,ymanca->creailfuturo(forseunacopiadif)aspettandoy

    
posta Jack Shade 24.06.2014 - 16:54
fonte

2 risposte

8

Sono state fatte promesse per risolvere problemi come questo; funzionano davvero bene in linguaggi funzionali (li ho usati ampiamente in Javascript, dove curiosamente jQuery in realtà ha la peggiore implementazione di essi - vedi questo confronto ). La cosa strana dell'uso delle promesse è accettare che le cose sono più facili quando fai in modo che tutto le usi . Inquadrerò la mia risposta in termini JavaScript utilizzando la promessa libreria Q , poiché è quello che so meglio - scuse se questa non è la tua tazza o "tè e due scuse per rispondere a una domanda agnostica con una lingua e una libreria specifiche da avviare.

Una promessa è un wrapper per una funzione di callback. In molte librerie, questa è chiamata una funzione .then() . In termini più semplici, una promessa attende un ritorno, quindi chiama la funzione passata a then() . La semplicità mi ha confuso all'inizio, quindi lascia che usi il tuo esempio. Consentitemi di aggiornare x e y alle funzioni. Se sono funzioni che restituiscono promesse (come molte librerie pesanti di asynch, come un accessor del database NodeJS), questo diventa banale.

Q.all([x(), y()]).then(function(results) {
  // Do some stuff with results, which is an enumerable collection containing
  // the in-order results of the promises passed in.
});

Il problema è che cosa succede se x() e y() non restituiscono le promesse? Come ho detto, la tua vita diventa più facile se tu fai loro restituisce promesse. Fortunatamente, qualsiasi libreria promessa semipreziosa fornisce anche strumenti per questo. In realtà, ci sono diversi modi per farlo in Q.

// Upgrade x into a promise returning function
function promise_x(/*x params...*/) {
  return Q.fcall(x(/*x params...*/));
}

// Upgrade x into a promise with a deferred
// Useful if you have some standard error handling specific to x-like functions
function defer_x(/*x params...*/) {
  var deferred = Q.defer();
  // If x is asynch, assume it takes a callback function with params of (error, result)
  x(/*x params...*/), function (error, result) {
    if (error) {
      deferred.reject(new Error(error));
    } else {
      // If you have some processing to do with the result of x (and not y), you can do
      // it here and return the modified result instead
      deferred.resolve(result);
    }
  });
  return deferred.promise;
}

Se ripeti il codice per la funzione y() , ritorni a dove puoi utilizzare Q.all() per attendere sia x() che y() da completare.

Q fornisce anche un'API per creare promesse, che è come una funzione wrapper per Q.defer() .

Tuttavia, la migliore funzionalità offerta da una libreria di promessa è la gestione aggregata degli errori. Espandendo il nostro primo esempio di Q.all , cosa succede se x o y lanciano un errore? Mentre quel codice è scritto ora, si perde. Considera quanto segue:

MyOverallFunction() {
  Q.all([x(), y()]).then(function(results) {
    // Do some stuff with results, which is an enumerable collection containing
    // the in-order results of the promises passed in.
    var combinedResult = synchronousFunction(result[0], result[1]);
    anotherAsyncPromiseFn(combinedResult)
      .then(function(result)) {
        return result;
      });
  }).then(function(result) {
     // Here, result is the return value of anotherAsyncPromiseFn
  }).error(function(err) {
     // This is the cool part. Any error from x, y, synchronousFunction, or
     // anotherAsyncPromiseFn will propagate to here. If you don't want to
     // handle it, just re-throw it (after logging it, if you prefer).
  });
}

Noterai anche nell'esempio precedente che ci sono diversi punti in cui viene dimostrata la combinazione dei metodi di sincronizzazione e asincrono.

In definitiva, gli strumenti a tua disposizione dipendono dalla tua lingua e dal tuo ambiente. Le promesse sono state implementate in più lingue rispetto al solo JS, e un altro idioma strettamente correlato dalla programmazione asincrona / funzionale è Futures . A dire il vero, se la tua lingua di scelta non ha una libreria Promessa, questa risposta sarà abbastanza inutile per te, ma spero che almeno la trovi interessante.

Aggiornamento: ora che menzioni Java, sembra che ci sia una libreria di buone intenzioni in JDefered . Non l'ho usato, ma sembra che i miei esempi possano essere applicati in modo abbastanza semplice.

    
risposta data 24.06.2014 - 17:43
fonte
1

Quello che stai descrivendo è un problema comune in programmazione reattiva . L'idioma è che il codice asincrono produca un Future che funge da punto di rendez-vous per un altro codice. Il codice che dipende dai risultati utilizza call-back (o call-forward, a seconda del punto di vista), che prendono il valore come verrà prodotto in futuro.

Con supporto linguistico adeguato ( Erlang , Scala ), l'uso di questi Future s diventa abbastanza semplice e diretto. Potresti anche voler indagare sugli attori in Akka . Questo fornisce un kit di strumenti per sistemi molto più complessi.

    
risposta data 24.06.2014 - 17:40
fonte

Leggi altre domande sui tag