1. Trang chủ
  2. » Công Nghệ Thông Tin

Sử dụng CoffeeScript trên máy chủ docx

9 326 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 9
Dung lượng 173,84 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Sử dụng CoffeeScript trên máy chủ Gọi tất cả các dịch vụ web Ứng dụng web trong Phần 3 đã dùng một từ khóa để thực hiện một tìm kiếm trên cả Google lẫn Twitter.. Để thực sự thực hiện các

Trang 1

Sử dụng CoffeeScript trên máy chủ

Gọi tất cả các dịch vụ web

Ứng dụng web trong Phần 3 đã dùng một từ khóa để thực hiện một tìm kiếm trên cả Google lẫn Twitter Về phía máy khách của của ứng dụng, bạn chỉ cần tạo mô hình giả định các kết quả từ máy chủ Để thực sự thực hiện các hàm như vậy, bạn cần phía máy chủ của ứng dụng để gọi các dịch vụ web được Google và Twitter cung cấp Cả hai công ty đều cung cấp các dịch vụ tìm kiếm rất đơn giản Tất cả những gì bạn cần làm là tạo ra các yêu cầu HTTP GET với các dịch vụ tìm kiếm Liệt kê 1 cho thấy một hàm tổng quát để tạo ra các yêu cầu HTTP GET

Liệt kê 1 Tìm nạp tài nguyên web

http = require "http"

fetchPage = (host, port, path, callback) ->

options =

host: host

port: port

path: path

req = http.get options, (res) ->

contents = ""

res.on 'data', (chunk) ->

contents += "#{chunk}"

res.on 'end', () ->

callback(contents)

req.on "error", (e) ->

console.log "Erorr: {e.message}"

Ở phần đầu của kịch bản lệnh này là câu lệnh require (yêu cầu), mà bạn đã thấy tóm tắt trong

Phần 1 của loạt bài này Đây là cú pháp nhập khẩu mô đun của Node.js hoặc ít nhất là phiên bản CoffeeScript của nó Phiên bản "nguyên gốc" sẽ là var http = require("http"); Trong bài này, bạn sẽ sử dụng một số mô đun lõi của Node.js (Thông tin chi tiết về việc cách hoạt động của các mô đun nằm ngoài phạm vi của bài viết này) Tất cả các mô đun được sử dụng trong bài này đều có sẵn cho bạn nếu bạn đã cài đặt Node.js (xem Phần 1) Với ví dụ trong Liệt kê 1, bạn đang sử dụng mô đun http, có cung cấp một vài lớp và các hàm có ích cho cả việc tạo ra lẫn tiếp nhận các yêu cầu HTTP

Sau đó Liệt kê 1 định nghĩa một hàm fetchPage nhận bốn tham số:

 Tên host (máy chủ) của tài nguyên

 port (cổng) của tài nguyên

 path (đường dẫn) của tài nguyên

 Một hàm callback (gọi lại)

Trang 2

Bất kỳ kiểu hàm Vào/Ra (I/O) nào trong Node.js về bản chất sẽ là không đồng bộ và do

đó sẽ cần một hàm callback để gọi khi nó hoàn thành Hàm fetchPage nhận một hàm

callback làm tham số thứ tư của mình Hàm fetchPage sẽ sử dụng ba tham số đầu tiên

để tạo ra một yêu cầu HTTP GET bằng cách sử dụng hàm get của mô đun http

Hàm fetchPage cũng nhận một hàm callback đã chuyển đi một cá thể ClientResponse

ClientResponse, là một đối tượng được định nghĩa trong mô đun http, thực hiện giao diện

ReadableStream (một giao diện cốt lõi trong Node.js) Nó là một giao diện không đồng bộ nhận hai sự kiện: data (dữ liệu) và end (kết thúc) Hàm duy nhất của nó được sử dụng để đăng ký gọi lại đến các sự kiện này Sự kiện dữ liệu xảy ra khi tiếp nhận dữ liệu từ tài nguyên mà bạn đã tạo

ra yêu cầu HTTP GET để lấy

Tất cả dữ liệu có thể được trả về cùng một lúc từ tài nguyên, nhưng phổ biến hơn, dữ liệu sẽ được gửi theo các bó (chunk) Khi nhận được mỗi bó, sự kiện dữ liệu được khởi động và hàm gọi lại được gọi ra Bạn đã tạo ra một biến có tên là contents (các nội dung); mỗi khi bạn nhận được một bó khác, bạn chỉ cần gắn thêm nó vào contents Khi đã nhận được tất cả dữ liệu, sự kiện end được khởi động Bây giờ bạn có tất cả dữ liệu, vì vậy bạn có thể chuyển contents trở lại cho hàm callback đã được chuyển tới hàm fetchPage Khi đã định nghĩa hàm đa năng này, chúng ta hãy tạo ra một số hàm chuyên dụng hơn cho các API tìm kiếm của Google và Twitter, như trong Liệt kê 2

Liệt kê 2 Các hàm tìm kiếm Google và Twitter

googleSearch = (keyword, callback) ->

host = "ajax.googleapis.com"

path = "/ajax/services/search/web?v=1.0&q=#{encodeURI(keyword)}"

fetchPage host, 80, path, callback

twitterSearch = (keyword, callback) ->

host = "search.twitter.com"

path = "/search.json?q=#{encodeURI(keyword)}"

fetchPage host, 80, path, callback

Có hai hàm được định nghĩa trong Liệt kê 2:

 googleSearch, nhận một keyword (từ khóa) và một hàm callback Nó ấn định máy chủ, tạo động đường dẫn bằng cách sử dụng phép nội suy chuỗi của CoffeeScript và sau

đó sử dụng hàm fetchPage

 twitterSearch, rất giống với googleSearch nhưng có máy chủ và giá trị đường dẫn khác

Đối với cả hai giá trị đường dẫn, bạn sử dụng phép nội suy chuỗi và hàm encodeURI tiện dụng của JavaScript để xử lý bất kỳ khoảng trống hoặc các ký tự đặc biệt khác nào Vì bạn có các hàm tìm kiếm này, nên bạn có thể tạo ra một hàm chuyên dụng cho một kịch bản tìm kiếm kết hợp

Trang 3

Về đầu trang

Kết hợp các hàm không đồng bộ

Có một vài cách để bạn có thể thực hiện tìm kiếm kết hợp trên Google và Twitter Bạn có thể gọi

googleSearch và sau đó, trong hàm callback, gọi twitterSearch, hoặc ngược lại Tuy nhiên, kiến trúc không đồng bộ/gọi lại của Node.js cho phép bạn làm những việc này một cáchđẹp đẽ hơn và hiệu quả hơn Liệt kê 3 hiển thị tìm kiếm kết hợp

Liệt kê 3 Tìm kiếm cả Google lẫn Twitter

combinedSearch = (keyword, callback) ->

data =

google : ""

twitter : ""

googleSearch keyword, (contents) ->

contents = JSON.parse contents

data.google = contents.responseData.results

if data.twitter != ""

callback(data)

twitterSearch keyword, (contents) ->

contents = JSON.parse contents

data.twitter = contents.results

if data.google != ""

callback(data)

Hàm combinedSearch có một chữ ký mà bây giờ đã quen thuộc: nhận một từ khóa và một hàm gọi lại Sau đó, nó tạo ra một cấu trúc dữ liệu cho các kết quả tìm kiếm kết hợp được gọi là data Đối tượng data có một trường google và một trường twitter, cả hai đều được khởi tạo như các chuỗi rỗng Bước tiếp theo gọi hàm googleSearch Trong hàm gọi lại của nó, bạn phân tích cú pháp các kết quả từ Google bằng cách sử dụng hàm JSON.parse tiêu chuẩn Văn bản JSON được trả về từ Google được phân tích cú pháp thành một đối tượng JavaScript Sử dụng đối tượng này để thiết lập giá trị của trường data.google Sau khi gọi googleSearch, hãy gọi

twitterSearch Hàm callback của nó rất giống với hàm callback dùng cho googleSearch Điều quan trọng cần hiểu rằng trong cả hai hàm gọi lại mà bạn kiểm tra để xem liệu bạn có dữ liệu từ hàm gọi lại khác không Bạn không biết hàm gọi lại nào sẽ hoàn thành trước tiên Vì vậy, hãy kiểm tra để xem liệu bạn có dữ liệu từ cả Google lẫn Twitter không Một khi bạn làm điều

đó, bạn gọi hàm callback đã được chuyển tới hàm combinedSearch Bây giờ bạn có một hàm

sẽ tìm kiếm cả Google lẫn Twitter và đưa ra các kết quả kết hợp Nhiệm vụ tiếp theo là trưng ra hàm này cho trang web mà bạn đã tạo ra trong Phần 3 của loạt bài này Tất cả những gì bạn phải làm là viết một máy chủ web

Về đầu trang

Một máy chủ web CoffeeScript

Trang 4

Lúc này, bạn có:

 Một trang web có thể gửi các từ khoá và hiển thị các kết quả tìm kiếm

 Một hàm có thể dùng một từ khóa và tạo ra các kết quả tìm kiếm từ Google và Twitter

Cái gì gắn kết những thứ này lại với nhau? Bạn có thể gọi nó là một máy chủ web, máy chủ ứng dụng, hoặc thậm chí phần mềm trung gian Bất kể bạn muốn gọi nó là gì, không cần dùng nhiều

mã CoffeeScript để viết nó

Máy chủ web cần đáp ứng hai mục đích Rõ ràng, nó cần nhận các yêu cầu cho việc tìm kiếm kết hợp Nó cũng cần cung cấp tài nguyên tĩnh mà bạn đã tạo ra trong Phần 3 Bạn đang tạo ra một ứng dụng web, do đó, bạn phải chú ý đến các quy định Các cuộc gọi tìm kiếm phải đi tới cùng một nơi đã tạo ra trang web Trước tiên hãy xử lý tài nguyên tĩnh Liệt kê 4 cho thấy một hàm để cung cấp tài nguyên tĩnh

Liệt kê 4 Cung cấp tài nguyên tĩnh

path = require "path"

fs = require "fs"

serveStatic = (uri, response) ->

fileName = path.join process.cwd(), uri

path.exists fileName, (exists) ->

if not exists

response.writeHead 404, 'Content-Type': 'text/plain'

response.end "404 Not Found #{uri}!\n"

return

fs.readFile fileName, "binary", (err,file) ->

if err

response.writeHead 500,

'Content-Type': 'text/plain'

response.end "Error #{uri}: #{err} \n"

return

response.writeHead 200

response.write file, "binary"

response.end()

Hàm serveStatic xử lý các yêu cầu về nguồn tài nguyên tĩnh trong ứng dụng web Lưu ý rằng bạn cần sử dụng thêm hai mô đun Node.js nữa:

 path chỉ đơn giản là một thư viện tiện ích để xử lý các đường dẫn tệp

 Hệ thống tệp, hoặc fs, cung cấp tất cả Vào/Ra của tệp trong Node.js và về cơ bản là một trình bao gói dựa trên các hàm POSIX tiêu chuẩn

Hàm serveStatic nhận hai tham số:

 uri về bản chất là một đường dẫn tương đối đến tệp tĩnh đang được một trình duyệt web yêu cầu

Trang 5

 Một đối tượng ServerResponse, là một kiểu khác được định nghĩa trong mô đun http Ngoài nhiều thứ khác, nó mang lại cho bạn một luồng để ghi dữ liệu vào bất cứ thứ gì đã tạo ra yêu cầu HTTP GET về tài nguyên

Trong hàm serveStatic, chuyển đường dẫn tương đối đến tệp thành một đường dẫn tuyệt đối bằng cách sử dụng process.cwd Đối tượng process (tiến trình) là một đối tượng chung

(global), đại diện cho tiến trình hệ thống mà Node.js đang chạy trên đó Phương thức cwd của nó cung cấp thư mục làm việc hiện tại Sử dụng mô đun path để kết hợp thư mục làm việc hiện tại

và đường dẫn tương đối đến tệp mà bạn muốn; kết quả là đường dẫn tuyệt đối Với đường dẫn tuyệt đối, bạn có thể sử dụng lại mô đun path để kiểm tra xem tệp có tồn tại hay không Việc kiểm tra xem tệp có tồn tại không liên quan đến I/O (Vào/Ra), cho nên nó là một hàm không đồng bộ Chuyển cho nó fileName (tên tệp) và một hàm gọi lại Hàm gọi lại nhận một giá trị Boolean, cho bạn biết liệu tệp tồn tại hay không Nếu nó không tồn tại, thì bạn cần viết một thông báo HTTP 404 " không tìm thấy tệp"

Nếu tệp tồn tại, thì bạn cần đọc nội dung của nó bằng cách sử dụng mô đun fs và phương thức

readFile, phương thức readFile là không đồng bộ Nó nhận fileName, một kiểu và một hàm gọi lại Hàm gọi lại nhận hai thông số:

 Một tham số lỗi cho biết bất kỳ vấn đề gì khi đọc tài nguyên từ hệ thống tệp Nếu có vấn

đề, một thông báo lỗi HTTP 500 được trả ngược lại tới phía máy khách

 Nếu không có vấn đề gì, một thông báo HTTP 200 OK được viết và các nội dung của tệp được gửi lại tới phía máy khách

Hàm này xử lý trường hợp cung cấp các tệp tĩnh tương đối dễ dàng Phần tiếp theo sẽ thảo luận

về kịch bản khó hơn, ở đó bạn cần đáp ứng động với một yêu cầu tìm kiếm

Về đầu trang

Các đáp ứng động và máy chủ

Ví dụ máy chủ web chủ yếu xử lý các yêu cầu tài nguyên tĩnh và các yêu cầu tìm kiếm động Chiến lược là sử dụng một URL cụ thể để xử lý các yêu cầu tìm kiếm và sau đó chuyển các yêu cầu khác tới hàm serveStatic Hãy sử dụng URL tương đối là /doSearch cho các yêu cầu tìm kiếm Liệt kê 5 cho thấy mã của máy chủ web

Liệt kê 5 Máy chủ web CoffeeScript

url = require "url"

server = http.createServer (request, response) ->

uri = url.parse(request.url)

if uri.pathname is "/doSearch"

doSearch uri, response

else

serveStatic uri.pathname, response

server.listen 8080

console.log "Server running at http://127.0.0.1:8080"

Trang 6

Một lần nữa, kịch bản lệnh này bắt đầu bằng cách nạp một mô đun Node.js Mô đun url là một thư viện có ích để phân tích cú pháp các URL Bước tiếp theo là tạo ra máy chủ web bằng cách

sử dụng mô đun http mà bạn nạp trong Liệt kê 1 Sử dụng phương thức createServer của mô đun đó, phương thức này nhận một hàm gọi lại sẽ được gọi mỗi khi có yêu cầu được gửi đến máy chủ web Hàm gọi lại có hai tham số: một cá thể ServerRequest và một cá thể

ServerResponse Cả hai kiều đều được định nghĩa trong mô đun http Trong hàm gọi lại này, việc phân tích cú pháp URL của yêu cầu đã được gửi đến máy chủ bằng cách sử dụng phương thức parse (phân tích cú pháp) của mô đun url Việc này sẽ cung cấp cho bạn một đối tượng URL và bạn có thể sử dụng thuộc tính pathname (tên đường dẫn) của nó để nhận được đường dẫn tương đối Nếu pathname là /doSearch, bạn gọi hàm doSearch (được thảo luận dưới đây) Nếu không, hãy gọi hàm serveStatic từ Liệt kê 5 Liệt kê 6 cho thấy cách doSearch hoạt động

Liệt kê 6 Xử lý các yêu cầu tìm kiếm

doSearch = (uri, response) ->

query = uri.query.split "&"

params = {}

query.forEach (nv) ->

nvp = nv.split "="

params[nvp[0]] = nvp[1]

keyword = params["q"]

combinedSearch keyword, (results) ->

response.writeHead 200, 'Content-Type': 'text/plain'

response.end JSON.stringify results

Hàm doSearch phân tích cú pháp chuỗi truy vấn đối với URL, mà có thể tìm thấy nó trong thuộc tính query (truy vấn) của đối tượng uri Chia nhỏ chuỗi truy vấn này ra bằng cách tách chuỗi này tại vị trí các ký tự & Sau đó chia tách từng chuỗi con tại vị trí dấu bằng để nhận được các cặp giá trị- tên từ chuỗi truy vấn Hãy lưu trữ từng cặp tên-giá trị vào đối tượng params Lấy ra tham số "q" để có được từ khóa mà bạn muốn tìm kiếm Chuyển từ khóa này tới hàm

combinedSearch trong Liệt kê 3 Bạn phải chuyển cho hàm này một hàm gọi lại Hàm gọi lại ví

dụ chỉ cần viết một thông báo HTTP 200 OK và chuyển các kết quả tìm kiếm thành một chuỗi bằng cách sử dụng hàm tiêu chuẩn JSON.stringify

Đó là tất cả những gì bạn cần cho máy chủ Trong phần tiếp theo, hãy xem cách móc nối máy chủ này vào mã máy khách trong Phần 3 của loạt bài này

Về đầu trang

Gọi máy chủ tìm kiếm

Trang 7

Trong Phần 3 bạn đã có một lớp MockSearch đã sử dụng dữ liệu giả đinh để cung cấp các kết quả tìm kiếm Bây giờ bạn sẽ định nghĩa một lớp mới để thực hiện một tìm kiếm thực gọi máy chủ tìm kiếm Liệt kê 7 cho thấy lớp tìm kiếm mới

Liệt kê 7 Lớp tìm kiếm thực

class CombinedSearch

search: (keyword, callback) ->

xhr = new XMLHttpRequest

xhr.open "GET", "/doSearch?q=#{encodeURI(keyword)}", true

xhr.onreadystatechange = ->

if xhr.readyState is 4

if xhr.status is 200

response = JSON.parse xhr.responseText

results =

google: response.google.map (result) ->

new GoogleSearchResult result

twitter: response.twitter.map (result) ->

new TwitterSearchResult result

callback results

xhr.send null

Lớp CombinedSearch có một phương thức duy nhất là search có chữ ký giống như phương thức search của MockSearch Nó nhận một từ khóa và một hàm gọi lại Bên trong hàm này:

 Sử dụng XMLHttpRequest, một "người bạn cũ" quen thuộc của bất kỳ nhà phát triển web nào, để tạo một yêu cầu HTTP đến máy chủ bằng cách sử dụng đường dẫn /doSearch và

từ khóa đã được chuyển đến hàm này

 Khi bạn nhận được một phản hồi, hãy phân tích cú pháp của nó bằng cách sử dụng

JSON.parse

 Tạo một đối tượng các kết quả với các trường google và twitter Tạo ra chúng bằng cách sử dụng các lớp GoogleSearchResult và TwitterSearchResult trong Phần 3

 Chỉ cần chuyển các kết quả trở lại hàm callback

Bây giờ, bạn chỉ cần sử dụng lớp doSearch này trong phương thức MockSearch Liệt kê 8 cho thấy cách sử dụng lớp CombinedSearch

Liệt kê 8 Sử dụng lớp CombinedSearch

@doSearch = ->

$ = (id) -> document.getElementById(id)

kw = $("searchQuery").value

appender = (id, data) ->

data.forEach (x) ->

$(id).innerHTML += "<p>#{x.toHtml()}</p>"

ms = new CombinedSearch

ms.search kw, (results) ->

Trang 8

appender("gr", results.google)

appender("tr", results.twitter)

Nếu bạn so sánh Liệt kê 8 với doSearch trong Phần 3, bạn sẽ không thấy nhiều sự khác biệt Điều duy nhất có khác là ở dòng thứ bảy Thay vì tạo một cá thể là MockSearch thì bạn tạo một

cá thể là CombinedSearch Những thứ khác đều như nhau Bạn nhận được từ khóa từ trang web, gọi tìm kiếm và sau đó gắn thêm các kết quả bằng cách gọi phương thức toHtml của từng đối tượng SearchResult Hình 1 cho thấy ứng dụng web với các kết quả tìm kiếm "sống" đến từ máy chủ

Hình 1 Chạy ứng dụng web ví dụ

Để nhận được các thay đổi bạn đã làm đối với mã phía máy khách, bạn cần biên dịch lại nó bằng

coffee -c search.coffee Để chạy ứng dụng, hãy sử dụng coffee search-server.coffee Sau đó, bạn có thể mở một trình duyệt tới địa chỉ http://127.0.0.1:8080 và thử một số truy vấn khác nhau

Về đầu trang

Kết luận

Trong bài này, bạn đã hoàn thành ứng dụng web bằng cách xây dựng thành phần phía máy chủ

để bổ sung cho mã phía máy khách trong Phần 3 Giờ đây, sau khi hoàn thành phần cuối của loạt

Trang 9

bài này, bạn đã có một ứng dụng hoàn chỉnh—tất cả được viết bằng CoffeeScript Bạn đã sử dụng rất nhiều tính năng của Node.js đã cho phép bạn sử dụng CoffeeScript như một công nghệ phía máy chủ

Một hạn chế đáng trách của Node.js là nó không chặn các hàm callback khi gọi từ tầng này sang tầng khác Điều này có thể khiến cho việc tư duy sắp xếp/phân loại khó khăn và với cú pháp dài dòng của JavaScript thậm chí còn khiến mọi việc phức tạp hơn CoffeeScript không thay đổi nhu cầu sử dụng của tất cả các hàm callback, nhưng với cú pháp rõ ràng của nó đã giúp dễ viết và dễ hiểu những đoạn mã như thế này hơn một chút

Ngày đăng: 09/03/2014, 04:20

HÌNH ẢNH LIÊN QUAN

Hình 1. Chạy ứng dụng web ví dụ - Sử dụng CoffeeScript trên máy chủ docx
Hình 1. Chạy ứng dụng web ví dụ (Trang 8)

TỪ KHÓA LIÊN QUAN

w