很高兴从yesj的ajax请求中获取数据

edg*_*her 7 haskell yesod

我正在尝试创建使用AJAX与服务器通信的简单页面(Yesod).到目前为止,我设法从服务器传递数据,但我不知道如何使用服务器处理程序(putJsonpR)获取客户端数据.

这是我到目前为止:

    {-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
    {-# LANGUAGE QuasiQuotes       #-}
    {-# LANGUAGE RecordWildCards   #-}
    {-# LANGUAGE TemplateHaskell   #-}
    {-# LANGUAGE TypeFamilies      #-}

    import Yesod
    import Database.PostgreSQL.Simple
    import Database.PostgreSQL.Simple.FromRow
    import Database.PostgreSQL.Simple.ToRow
    import Database.PostgreSQL.Simple.ToField
    import Data.Aeson
    import Data.Text (Text)
    import Control.Applicative
    import Control.Monad
    import GHC.Generics

    data HelloWorld = HelloWorld

    mkYesod "HelloWorld" [parseRoutes|
    / HomeR GET
    /json/#Int JsonR GET
    /json JsonpR PUT
    |]

    instance Yesod HelloWorld

    data Person = Person {
        personId :: Int,
        name :: String,
        age :: Int
    } deriving (Show,Generic)

    instance FromJSON Person
    instance ToJSON Person

    instance FromRow Person where
        fromRow = Person <$> field <*> field <*> field

    instance ToRow Person where
        toRow d = [ toField (personId d), toField (name d), toField (age d)]

    getConnectionString = do
        cnn <- connect defaultConnectInfo {
                connectHost = "127.0.0.1"
                , connectPort = 5432
                , connectUser = "postgres"
                , connectPassword = "123456"
                , connectDatabase = "tst"
                }
        return (cnn)

    getPerson id = do
        cnn <- getConnectionString
        xs <- query cnn "select \"PersonId\", \"Name\", \"Age\" from \"Person\" where \"PersonId\" = ?" (Only (id :: Int))  :: IO [Person]
        return (head xs)

    getHomeR :: Handler ()
    getHomeR = sendFile typeHtml "staticpage.html"

    getJsonR :: Int -> Handler Value
    getJsonR personId = do
        person <- liftIO $ getPerson personId
        returnJson $ person

    putJsonpR :: Handler Value
    putJsonpR = do
        person <- parseJsonBody_ :: Handler Person
        returnJson $ person

    main :: IO ()
    main = warp 3000 HelloWorld
Run Code Online (Sandbox Code Playgroud)

这是HTML页面:

    <html>
        <head>
             <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
            <script type="text/javascript">
                function getPerson () {
                    $.ajax({
                    url: "/json/" + 1,
                    success: function (data) {
                        alert (data.personId + " - " + data.name + " - " + data.age);
                    },
                    dataType: "json"
                    }); 
                }

                function save() {
                    $.ajax({
                    url: "/json",
                    type: "PUT",
                    data: { "personId": 123, "name": "from gui", "age": 123 },
                    success: function (data) {
                        alert (data.personId + " - " + data.name + " - " + data.age);
                    },
                    error: function(xhr, status, error) {
                      alert(xhr.responseText);
                    },
                    dataType: "json"
                    }); 
                }
            </script>
        </head>
        <body>
            <input type="button" onclick="getPerson()" value="get" />
            <br />
            <br />
            <br />
            <input type="button" onclick="save()" value="put" />
        </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

我收到了AJAX错误消息:"读取失败:不是有效的json值"

另外,有没有办法输出我从AJAX请求得到的任何东西?
就像是:

    putSomethingR = do
        liftIO $ print $ whateverCameFromAjax
        -- rest of handler
Run Code Online (Sandbox Code Playgroud)

Mic*_*man 5

在FP Haskell Center上汇总了这样做的样本.代码也包含在下面.

您最初编写的内容存在于Javascript代码中.你的jQuery参数告诉它创建一个URL编码的请求体.您需要手动将JSON呈现为文本,然后关闭处理processData: false.

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE TypeFamilies      #-}
import           Yesod
import           Yesod.Form.Jquery (YesodJquery (urlJqueryJs))
import Data.Conduit
import qualified Data.Conduit.Text as CT
import qualified Data.Conduit.List as CL
import qualified Data.Text as T

data App = App

mkYesod "App" [parseRoutes|
/ HomeR GET
/echo-body EchoBodyR PUT
|]

instance Yesod App
instance YesodJquery App

getHomeR :: Handler Html
getHomeR = defaultLayout $ do
    setTitle "Yesod + Ajax"
    getYesod >>= addScriptEither . urlJqueryJs
    [whamlet|
        <button #echo>Echo body
    |]
    toWidget script

script = [julius|
$(function(){
    $("#echo").click(function(){
        $.ajax({
            // sending a JSON encoded body
            contentType: "application/json",
            // don't process the body, we'll render data into a valid string
            processData: false,
            url: "@{EchoBodyR}",
            type: "PUT",
            // notice the usage of stringify here
            data: JSON.stringify([{name:"Alice",age:25}, {name:"Bob",age:30}]),
            success: function(data) {
                alert(data.body);
            },
            // this only refers to the data type of the *returned* data
            dataType: "json"
        });
    });
});
|]

putEchoBodyR :: Handler Value
putEchoBodyR = do
    texts <- rawRequestBody $$ CT.decode CT.utf8 =$ CL.consume
    return $ object ["body" .= T.concat texts]

main :: IO ()
main = warpEnv App
Run Code Online (Sandbox Code Playgroud)


Gab*_*iba 4

在“GET”方面,由于您不使用持久模板,而是使用 Database.PostgreSQL.Simple.query 中的数据库级 sql,使用真实的数据库标识符解决了错误。

getPerson id = do
    cnn <- getConnectionString
    xs <- query cnn "select \"id\", \"name\", \"age\" from \"person\" where \"id\" = ?" (Only (id :: Int))  :: IO [Person]
    return (head xs)
Run Code Online (Sandbox Code Playgroud)

在“PUT”方面,您的 staticpage.html jquery 脚本上存在 ajax 解析错误,当您将“data”字段括在单引号中时已更正:

   function save() {
       $.ajax({
       url: "/json",
       type: "PUT",
       data: '{ "personId": 123, "name": "from gui", "age": 123 }',
       ...
       dataType: "json"
       ...
Run Code Online (Sandbox Code Playgroud)

第三。您可以使用以下命令记录ajax 输出

$(logDebug) (show whatEverCameFromAjax)
Run Code Online (Sandbox Code Playgroud)

如果您使用 yesod 脚手架,则来自 MonadLogger 实例 monad。

  • 我需要输入什么来代替“whateverCameFromAjax”才能将其记录下来? (2认同)