2016-04-29 103 views
1

我有用Eff s和Aff s編寫的以下程序。按預期運行。這是它打印出給定的Int,它做了異步計算。爲什麼我的效果被調用兩次?

type JsonResponse = AffjaxResponse Json 
access :: forall e m. Aff (ajax :: AJAX | e) (Either Error JsonResponse) 
access = attempt $ get "http://localhost:8080/livesys/Robert" 

staging :: forall e. Int -> Eff (console :: CONSOLE | e) Int 
staging i = do 
    liftEff $ log $ ">>" ++ show i 
    return i 

main :: forall a. Int -> Aff (ajax :: AJAX, console :: CONSOLE| a) Int 
main state = do 
    s <- liftEff $ staging state 
    a <- liftAff access 
    return s 

如果我改變調用但內部秩序main然後神祕的東西發生了:

main :: forall a. Int -> Aff (ajax :: AJAX, console :: CONSOLE| a) Int 
main state = do 
    a <- liftAff access 
    s <- liftEff $ staging state 
    return s 

功能staging現在被稱爲兩次!武漢理工大學?

有人可以解釋一下嗎?

感謝您的幫助

+0

如果您在'main'中刪除對'liftAff'的調用會發生什麼?我不認爲這是必要的。 (不要原諒這種行爲,這確實看起來是錯誤的;我只是想診斷) – hdgarrood

+0

沒有變化。唯一有點「異國情調」的是我使用的是https://github.com/sectore/purescript-webpack-vanilla-hmr。儘管如此,它應該表現一貫(或者總是2次或者總是一次,但是在不同的訂單上沒有不同) – robkuz

+0

同意。你可以通過'psc-bundle'運行上述程序並將其上傳到一個pastebin? – hdgarrood

回答

0

很可能的情況下的異常被拋出,而不是通過處理誤差函數在AFF實例。這會導致在與attempt一起使用時重複調用成功功能。

module Main where 

import Prelude 
import Data.Either (Either(..)) 
import Control.Monad.Eff (Eff) 
import Control.Monad.Eff.Console (log) 
import Control.Monad.Eff.Exception (Error, EXCEPTION, throwException, error) 
import Control.Monad.Aff (Aff, makeAff, liftEff', launchAff, attempt) 

raise = throwException <<< error 


myAff :: forall e. Aff e String 
myAff = _unsafeInterleaveAff $ makeAff doIt 
    where 
    doIt _ success = do 
     log "operation" 
     raise "it's dead jim" 
     success "done" 

main = do 
    launchAff $ do 
    liftEff' $ log "start" 
    myAff 

foreign import _unsafeInterleaveAff :: forall e1 e2 a. Aff e1 a -> Aff e2 a 

此代碼導致doIt被調用兩次,但是當Aff調用被顛倒時不會。

附加:

雖然這個功能似乎有點奇怪。也許用更多這樣的替代attempt

exports._attempt = function (Left, Right, aff) { 
    return function(success, error) { 
    var affCompleted = false; 
    try { 
     return aff(function(v) { 
     affCompleted = true 
     success(Right(v)); 
     }, function(e) { 
     affCompleted = true 
     success(Left(e)); 
     }); 
    } catch (err) { 
     if (affCompleted) { 
     throw err; 
     } else { 
     success(Left(err)); 
     } 
    } 
    }; 
} 
相關問題