2016-12-14 3 views
2

Ich versuche, entweder Monad zu verwenden, um meine Daten durchzuleiten, das Problem ist, dass ich nicht herausfinden kann, wie ich meine Monad bewusst machen die Operation, die asyncSo machen Sie Monaden beachten von Async-Funktionen (Promises/Future)

hier ist, was ich habe

let processData = Either.either(_sendError, _sendResponse) 

processData(_getDataGeneric(queryResult) 
    .chain(_findDevice) 
    .chain(_processRequest) 
); 

queryresult ist das, was ich aus der Datenbank selbst holen.

das Problem ist, dass das Holen des Ergebnisses nur in der Mitte der Pipeline ist. , was ich will, ist dies

ValidateUserInput -> GetDataFromDB -> ProcessData 

processAll(_fetchFromDB(userId) 
    .getDataGeneric 
    .chain(_findDevice) 
    .chain(_processRequest)) 


//_fetchFromDB , Mongoose Query 
function _fetchFromDB(userId){ 
     return myModel.findOne({id:userId}).exec() 
            .then(function(result){ 
            return Right(result) 
           }).catch((err)=>Left(err)) 
    } 

, wenn das Ergebnis gültig von DB ist, wird es eine Rechtsinstanz zurückgeben, und wenn es irgendeine Art von Fehler ist, wird er zurückkehren Left

das Problem, dass diese Operation ist ist Async und ich bin mir nicht sicher, wie ich meine Entweder-Monade dazu bringen kann, damit umzugehen und sie zu verarbeiten.

Irgendwelche Ideen, wie ich meine Monad auf Promises in ihrer Funktionsweise aufmerksam machen kann?

+0

Gibt es ein Return-Schlüsselwort vor der 'Model.findOne()' Zeile? – Sgnl

Antwort

1

Wie Sie sehen, kann ein Either Typ nur Werte darstellen, die bereits realisiert wurden, während der asynchrone Vorgang etwas darstellt, das in Zukunft ausgewertet werden kann.

Ein Promise kombiniert bereits das Verhalten eines Either, indem es die Möglichkeit von sowohl Fehler als auch erfolgreichen Werten darstellt. Es erfasst auch das Verhalten der Verkettung von Operationen im monadischen Stil, indem es then ermöglicht, eine andere Promise Instanz zurückzugeben.

Wenn Sie jedoch in etwas interessiert sind, ähnlich wie bei einem Promise, die näher an einer Either verhält (und folgt auch die Fantasy Land spec) dann könnten Sie an einer der Future Implementierungen aussehen wie Fluture

z.B

import Future from 'fluture'; 

const processAll = Future.fork(_sendError, _sendResponse); 

const _fetchFromDB = 
    Future.fromPromise(userId => myModel.findOne({ id: userId }).exec()) 

processAll(_fetchFromDB(userId) 
    .chain(getDataGeneric) 
    .chain(_findDevice) 
    .chain(_processRequest)) 
+0

Ah ich sehe! Das war, was ich vermutete. Ich verstehe, dass die Versprechungen sehr ähnlich dem Entweder-Typ sind, mit Zurückweisungs- (Links) und Auflösungsverhalten (Rechts). Was ich wirklich tun wollte, war die Fehlerbehandlung zu konsolidieren. ZB übergeben Sie die Rechte Seite eines gegebenen Versprechens in die rechte Seite beider Kette, und verarbeiten Sie die angegebenen Daten. Wenn es einen Fehler gegeben hat, interessiert mich wirklich der Catch-Teil des Versprechens, und ich wollte diesen Teil meines Fehlerbehandlungsflusses machen. Ansonsten musste ich mit der Entweder-Funktion-Pipeline und dem promise.catch-Teil des Fehlers umgehen. Gibt es einen besseren Weg? –

+0

Es scheint, dass fluture mit der Promise-Spezifikation interagieren kann. Gibt es eine Möglichkeit für mich, Future von ramda Fantasy land auf die gleiche Weise zu nutzen? –

+0

Wenn Sie eine 'fromPromise'-Funktion mit Ramda Fantasy erstellen möchten, sieht das so aus:' fromPromise = fn => (... args) => Zukunft ((rej, res) => fn (... args) .then (res, rej)) ' –