2016-12-14 160 views
2

我正嘗試使用Monad來管通過我的數據,問題是我無法弄清楚如何讓我的Monad知道這是異步如何使Monads知道異步函數(承諾/未來)

這裏的工作是我

let processData = Either.either(_sendError, _sendResponse) 

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

QueryResult中是我從數據庫本身獲取。

問題是取回結果只是在管道中間。 我要的是這個

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

如果結果是有效的,從數據庫,它會返回一個正確的實例,如果有任何類型的錯誤,它會返回左

的問題是,這種操作是異步,我不知道如何讓我的Monad處理它並處理它。

關於如何讓我的Monad意識到Promise在操作中的任何想法?

+0

在Model.findOne()行之前是否存在返回關鍵字? – Sgnl

回答

1

正如您所看到的,Either類型只能表示已經實現的值,而異步操作表示將來可能評估的某些值。

A Promise已經結合了Either的行爲,通過表示錯誤和成功值的可能性。它還通過允許then返回另一個Promise實例來捕獲monadic風格的操作鏈的行爲。

然而,如果你有興趣在類似Promise更緊密地表現到Either(也遵循Fantasy Land SPEC)的東西,那麼你可能會喜歡在Future實現這樣的一個看成Fluture

例如

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

啊我明白了!那是我懷疑發生的事情。我瞭解承諾類似於非常類型,拒絕(左)和解決(右)行爲。我真正想做的是整合錯誤處理。 例如,將給定承諾的右側傳遞給任一鏈的右側,並處理給定的數據。如果發生故障,我真的很在意承諾的Catch部分,並且我希望將它作爲我的錯誤處理流程的一部分。否則,我需要處理Either函數管道,以及錯誤的promise.catch部分。 有沒有更好的方法? –

+0

看起來似乎可以與諾言規範接口。有沒有辦法讓我以同樣的方式使用夢幻之地的未來? –

+0

如果您想使用Ramda Fantasy創建'fromPromise'函數,它看起來像'fromPromise = fn =>(... args)=> Future((rej,res)=> fn(... args)那麼(res,rej))' –