2014-05-05 12 views
7

Tôi đang cố gắng tạo trang đơn giản sử dụng AJAX để giao tiếp với máy chủ (Yesod). Cho đến nay, tôi đã quản lý để truyền dữ liệu từ máy chủ, nhưng tôi không biết cách lấy dữ liệu máy khách với trình xử lý máy chủ (putJsonpR).Nóng để lấy dữ liệu từ yêu cầu ajax với yesod

Đây là những gì tôi có cho đến nay:

{-# 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 

Và đây là trang 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> 

tôi đã nhận lỗi AJAX hộ thông điệp: "đọc Không: không phải là một giá trị json hợp lệ"

Ngoài ra, có cách nào để xuất ra bất cứ điều gì tôi nhận được từ yêu cầu AJAX không?
Cái gì như:

putSomethingR = do 
     liftIO $ print $ whateverCameFromAjax 
     -- rest of handler 

Trả lời

4

Trên "GET" phụ, kể từ khi bạn không sử dụng dai dẳng mẫu nhưng mức db sql từ Database.PostgreSQL.Simple.query, sử dụng thực định cơ sở dữ liệu, giải quyết lỗi.

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

Trên "PUT" bên, có một lỗi phân tích cú pháp ajax trên kịch bản jquery staticpage.html của bạn, điều chỉnh khi bạn kèm theo "dữ liệu" trường trong dấu nháy đơn:

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

lần thứ 3. Bạn có thể log đầu ra ajax của bạn với

$(logDebug) (show whatEverCameFromAjax) 

từ một trường hợp đơn nguyên MonadLogger, nếu bạn sử dụng giàn giáo Yesod.

+2

Tôi cần nhập gì thay vào 'whateverCameFromAjax' để đăng nhập? – edgecrusher

5

Tôi đã đặt cùng nhau a sample of doing this on FP Haskell Center. Mã được bao gồm dưới đây là tốt.

Vấn đề với những gì bạn viết ban đầu là trong mã Javascript. Các tham số của bạn cho jQuery yêu cầu nó tạo ra một thân yêu cầu được mã hóa bằng URL. Bạn cần phải tự tạo JSON của mình thành văn bản và tắt chế biến với 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 
Các vấn đề liên quan