diff --git a/reflex-dom-core/src/Reflex/Dom/Xhr.hs b/reflex-dom-core/src/Reflex/Dom/Xhr.hs index 8bdf1e19..a06adad3 100644 --- a/reflex-dom-core/src/Reflex/Dom/Xhr.hs +++ b/reflex-dom-core/src/Reflex/Dom/Xhr.hs @@ -153,6 +153,7 @@ import Control.Lens import Control.Monad hiding (forM) import Control.Monad.IO.Class import Data.Aeson +import Data.IORef (newIORef, atomicModifyIORef') #if MIN_VERSION_aeson(1,0,0) import Data.Aeson.Text #else @@ -262,28 +263,34 @@ newXMLHttpRequestWithError req cb = do iforM_ (_xhrRequestConfig_headers c) $ xmlHttpRequestSetRequestHeader xhr maybe (return ()) (xmlHttpRequestSetResponseType xhr . fromResponseType) rt xmlHttpRequestSetWithCredentials xhr creds + -- Avoid handler being called more than once. + -- This is needed until jsaddle/ghcjs-dom: https://github.com/ghcjs/ghcjs-dom/issues/89 is fixed. + alreadyHandled <- liftIO $ newIORef False _ <- xmlHttpRequestOnreadystatechange xhr $ do readyState <- xmlHttpRequestGetReadyState xhr status <- xmlHttpRequestGetStatus xhr statusText <- xmlHttpRequestGetStatusText xhr - when (readyState == 4) $ do - t <- if rt == Just XhrResponseType_Text || isNothing rt - then xmlHttpRequestGetResponseText xhr - else return Nothing - r <- xmlHttpRequestGetResponse xhr - h <- case _xhrRequestConfig_responseHeaders c of - AllHeaders -> parseAllHeadersString <$> - xmlHttpRequestGetAllResponseHeaders xhr - OnlyHeaders xs -> traverse (xmlHttpRequestGetResponseHeader xhr) - (Map.fromSet id xs) - _ <- liftJSM $ cb $ Right - XhrResponse { _xhrResponse_status = status - , _xhrResponse_statusText = statusText - , _xhrResponse_response = r - , _xhrResponse_responseText = t - , _xhrResponse_headers = h - } - return () + when (readyState == 4) $ + handled <- liftIO $ atomicModifyIORef' alreadyHandled $ + \handled -> (True, handled) + unless handled $ do + t <- if rt == Just XhrResponseType_Text || isNothing rt + then xmlHttpRequestGetResponseText xhr + else return Nothing + r <- xmlHttpRequestGetResponse xhr + h <- case _xhrRequestConfig_responseHeaders c of + AllHeaders -> parseAllHeadersString <$> + xmlHttpRequestGetAllResponseHeaders xhr + OnlyHeaders xs -> traverse (xmlHttpRequestGetResponseHeader xhr) + (Map.fromSet id xs) + _ <- liftJSM $ cb $ Right + XhrResponse { _xhrResponse_status = status + , _xhrResponse_statusText = statusText + , _xhrResponse_response = r + , _xhrResponse_responseText = t + , _xhrResponse_headers = h + } + return () _ <- xmlHttpRequestSend xhr (_xhrRequestConfig_sendData c) return () return xhr