2015-11-02 10 views
13

Sto osservando le funzioni di gestione che restituiscono promesse con le funzioni Ramda diverse da pipeP. Sto cercando di confrontare le funzioni (una delle quali restituisce una promessa) con eguali in questo modo:Gestione della programmazione asincrona con Ramda

getSectionFromDb :: obj -> promise 
getSectionFromData :: obj -> number 

R.equals(
    getSectionFromDb, 
    getSectionFromData 
) 

Ci sono due fattori in gioco qui. First R.equals non valuterà le funzioni, ma il problema più grande è che sto confrontando una promessa a un numero.

C'è un modo funzionale per fare questo genere di cose (so che le funzioni non sono referenziali trasparenti, ma ci deve essere un modo di trattare con io)? C'è un modo per farlo Ramda?

Grazie.

+2

Sembra come se si volesse "elevare" la funzione "uguale" - prima nella promessa monade e poi nella funzione applicativa; sfortunatamente Ramda può solo sollevare liste. – Bergi

+0

Quindi vuoi una funzione '??? :: (obj -> Promessa ) -> (oggetto -> numero) -> (oggetto -> Promessa ) '? – Bergi

+0

@Bergi: la documentazione di Ramda non è del tutto soddisfacente, ma 'lift' ** [funziona su arbitrari' Functional Functional'] (https://github.com/ramda/ramda/blob/master/test/liftN js # L42-L45) **. –

risposta

3

È possibile utilizzare Promise.resolve per "avvolgere" un valore in una promessa.

getSectionFromDataPromise :: obj -> promise 
getSectionFromDataPromise = R.pipe(getSectionFromData , (val) => Promise.resolve(val)) 

In questo modo è possibile promuovere (sollevare) qualsiasi funzione che restituisce un valore normale a uno che restituisce una promessa.

Il sollevamento è un concetto essenziale in FP. È possibile visualizzare Array.map come una funzione che eleva una funzione che trasforma un valore in una funzione che trasforma una matrice di valori.

È possibile utilizzare Promise.all per scrivere una funzione che confronta le promesse e (ad esempio) genera un errore se non sono uguali.

function promiseEquals (f1, f2) { 
    return Promise.all([f1(), f2()]).then(function(vals) { 
    if(!R.equals(vals[0], vals[1])) {throw "The values aren't equal"} 
    return vals[0] 
    }) 
} 

Infine è possibile combinare i due:

promiseEquals(getSectionFromDataPromise, getSectionFromDb) 
    .then(function(val){ 
    console.log(val) 
    }) 
    .catch(function(val){console.log("Error "+val)}) 
+0

Is not (val) => Promise.resolve (val) solo un modo prolisso di dire Promise.resolve? – arcseldon

+0

idealmente si, in JS no. La funzione di risoluzione non è legata all'oggetto Promise. –

+1

@arcseldon Si potrebbe fare 'getSectionFromDataPromise = R.pipe (getSectionFromData, Promise.resolve.bind (Promise));' –

9

Lo so, la domanda è vecchia. Ma ramda ha alcune funzioni interessanti per comporre le funzioni di ritorno promessa: pipeP e composeP.

anche dare un'occhiata in regolare compose (pipe) e la sua implementazione Kleisli composeK (pipeK). Consentono di lavorare con strutture algebriche come Future o Task, che hanno lo stesso aspetto di Promise, ma sono sottoposte a valutazione lazy.