From 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:43:23 -0500 Subject: initial commit --- .../development_environment/index.html | 407 +++++++++++ .../flow_control_using_async/index.html | 135 ++++ .../express_nodejs/displaying_data/index.html | 98 +++ .../vi/learn/server-side/express_nodejs/index.html | 77 ++ .../server-side/express_nodejs/mongoose/index.html | 800 +++++++++++++++++++++ .../tutorial_local_library_website/index.html | 89 +++ files/vi/learn/server-side/first_steps/index.html | 46 ++ .../first_steps/introduction/index.html | 228 ++++++ files/vi/learn/server-side/index.html | 59 ++ 9 files changed, 1939 insertions(+) create mode 100644 files/vi/learn/server-side/express_nodejs/development_environment/index.html create mode 100644 files/vi/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html create mode 100644 files/vi/learn/server-side/express_nodejs/displaying_data/index.html create mode 100644 files/vi/learn/server-side/express_nodejs/index.html create mode 100644 files/vi/learn/server-side/express_nodejs/mongoose/index.html create mode 100644 files/vi/learn/server-side/express_nodejs/tutorial_local_library_website/index.html create mode 100644 files/vi/learn/server-side/first_steps/index.html create mode 100644 files/vi/learn/server-side/first_steps/introduction/index.html create mode 100644 files/vi/learn/server-side/index.html (limited to 'files/vi/learn/server-side') diff --git a/files/vi/learn/server-side/express_nodejs/development_environment/index.html b/files/vi/learn/server-side/express_nodejs/development_environment/index.html new file mode 100644 index 0000000000..f46ebd1a9f --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/development_environment/index.html @@ -0,0 +1,407 @@ +--- +title: Setting up a Node development environment +slug: Learn/Server-side/Express_Nodejs/development_environment +tags: + - Cài đặt + - Express + - Hướng dẫn + - hello world + - nodejs + - npm +translation_of: Learn/Server-side/Express_Nodejs/development_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}
+ +

Bây giờ bạn đã biết Express là gì, chúng tôi sẽ chỉ cho bạn cách cài đặt và kiểm tra một môi trường phát triển Node/Express trên Windows, Linux (Ubuntu) và macOS. Bất kể hệ điều hành bạn đang dùng là gì, bài này sẽ cho biết những thứ cần thiết để bắt đầu phát triển ứng dụng Express.

+ + + + + + + + + + + + +
Điều kiện tiên quyết: +

Biết mở Terminal / Command Prompt.
+ Biết cài đặt các gói trên hệ điều hành của bạn.

+
Mục tiêu:Cài đặt một môi trường phát triển cho Express (X.XX) trên máy tính của bạn.
+ +

Tổng quan môi trường phát triển Express

+ +

Node và Express rất dễ dàng cài đặt trên máy tính của bạn để bắt đầu phát triển ứng dụng web. Mục này cho biết tổng quan về những công cụ nào cần dùng, giải thích một số phương pháp đơn giản nhất để cài Node (và Express) trên Ubuntu, macOS và Windows, kèm theo là hướng dẫn kiểm tra bạn đã cài được chưa.

+ +

Môi trường phát triển Express là gì?

+ +

Môi trường phát triển Express bao gồm cài đặt Nodejs, trình quản lý gói NPM và (tuỳ chọn) Express Application Generator (trình khởi tạo ứng dụng Express) trên máy của bạn.

+ +

Nodetrình quản lý gói NPM được cài đặt cùng nhau từ một gói, trình cài đặt, trình quản lý gói của hệ điều hành hoặc từ mã nguồn (xem các phần sau). Express được cài đặt sau đó bởi NPM như một phụ thuộc (dependency) của ứng dụng web Express (cùng với các thư viện khác như template engines, database drivers, authentication middleware, middleware to serve static files, v.v...).

+ +

NPM có thể được dùng để cài Express Application Generator, một công cụ tiện dụng để tạo bộ khung ứng dụng web Express theo mô hình MVC. Công cụ này là tuỳ chọn vì bạn không cần phải sử dụng nó để tạo ứng dụng Express. Tuy nhiên chúng tôi sẽ sử dụng, bởi vì nó giúp chúng ta bắt đầu dễ dàng hơn và cho chúng tâ cấu trúc ứng dụng dạng mô-đun.

+ +
+

Ghi chú: Không như một số web frameworks khác có môi trường phát triển không bao gồm một server rời. Trong Node / Express, một ứng dụng web tạo và chạy web server của nó!

+
+ +

Có những công cụ ngoại vi khác thường dùng trong môi trường phát triển bao gồm text editors hoặc IDEs để chỉnh sửa code và công cụ quản lý mã nguồn như Git để quản lý các phiên bản code khác nhau của bạn. Chúng tôi giả định bạn đã cài những công cụ này (đặc biệt là một text editor).

+ +

Những hệ điều hành nào được hỗ trợ?

+ +

Node có thể chạy trên Windows, macOS, nhiều bản distro của Linux, Docker, v.v... (có danh sách đầy đủ ở Nodejs Downloads page). Hầu hết mọi máy tính cá nhân đủ khả năng để chạy Node trong khi phát triển. Express chạy trong môi trường Node, do dó nó có thể chạy trên mọi nền tảng có Node.

+ +

Trong bài này chúng tôi hướng dẫn cài đặt cho Windows, macOS và Ubuntu Linux.

+ +

Bạn nên sử dụng Node/Express phiên bản nào?

+ +

Có nhiều phiên bản Node — những bản mới được vá lỗi, hỗ trợ nhiều hơn cho các chuẩn ECMAScript (JavaScript) gần đây, và nâng cấp các Node APIs.

+ +

Nhìn chung, bạn nên sử dụng bản LTS (được hỗ trợ dài hạn) mới nhất bởi vì nó ổn định hơn các các bản "current" mà vẫn có các tính năng tương đối mới gần đây (và vẫn được tích cực bảo trì). Bạn nên sử dụng phiên bản Current nếu bạn muốn dùng tính năng không có ở bản LTS.
+
+ Với Express, bạn nên luôn sử dụng bản mới nhất.

+ +

Còn cơ sở dữ liệu và các phụ thuộc khác thì sao?

+ +

Các phụ thuộc khác như database drivers, template engines, authentication engines, v.v.. là một phần của ứng dụng, được import vào môi trường ứng dụng bởi sử dụng trình quản lý gói NPM. Chúng tôi sẽ nói đến trong các bài cụ thể sau.

+ +

Cài đặt Node

+ +

Để sử dụng Express, trước hết bạn phải cài Nodejstrình quản lý gói Node (NPM) trên hệ điều hành của bạn. Những mục sau hướng dẫn cách đơn giản nhất để cài Nodejs phiên bản LTS trên Ubuntu Linux 16.04, macOS và Windows 10.

+ +
+

Mẹo: Những mục bên dưới hướng dẫn cách dễ nhất để cài Node và NPM trên các nền tảng OS của chúng tôi. Nếu bạn đang dùng OS khác hoặc muốn xem các cách khác để cài thì xem tại  Installing Node.js via package manager (nodejs.org).

+
+ +

Windows và macOS

+ +

Cài đặt NodeNPM trên Windows và macOS đơn giản chỉ cần dùng trình cài đặt được cung cấp sẵn.

+ +
    +
  1. Tải trình cài đặt: +
      +
    1. Truy cập https://nodejs.org/en/
    2. +
    3. Chọn nút tải xuống bản LTS.
    4. +
    +
  2. +
  3. Click đúp chuột vào file đã tải và làm theo các hướng dẫn.
  4. +
+ +

Ubuntu 16.04

+ +

Cách đơn giản nhất để cài phiên bản LTS mới nhất của Node là sử dụng trình quản lý gói để lấy từ Ubuntu binary distributions repository. Đơn giản là chạy hai câu lệnh sau trong terminal:

+ +
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
+sudo apt-get install -y nodejs
+
+ +
+

Lưu ý: Không cài trực tiếp từ normal Ubuntu repositories bởi vì các bản Node ở đó quá cũ.

+
+ +
    +
+ +

Kiểm tra kết quả cài đặt

+ +

Cách đơn giản nhất để kiểm tra xem node đã được cài chưa là chạy lệnh "version" trong terminal/ command prompt và xem phiên bản in ra:

+ +
>node -v
+v8.11.3
+ +

Trình quản lý gói Nodejs (NPM) cũng được cài đặt luôn, kiểm tra tương tự:

+ +
>npm -v
+5.8.0
+ +

Một bài kiểm tra thú vị hơn là tạo một server rất cơ bản "thuần Node" đơn giản in ra "Hello World" trong trình duyệt của bạn khi truy cập đúng URL:

+ +
    +
  1. Copy đoạn mã sau vào một file đặt tên là hellonode.js. Đoạn mã này sử dụng các tính năng Node thuần (không dùng gì của Express) và một vài cú pháp ES6: + +
    //Load HTTP module
    +const http = require("http");
    +const hostname = '127.0.0.1';
    +const port = 3000;
    +
    +//Create HTTP server and listen on port 3000 for requests
    +const server = http.createServer((req, res) => {
    +
    +  //Set the response HTTP header with HTTP status and Content type
    +  res.statusCode = 200;
    +  res.setHeader('Content-Type', 'text/plain');
    +  res.end('Hello World\n');
    +});
    +
    +//listen for request on port 3000, and as a callback function have the port listened on logged
    +server.listen(port, hostname, () => {
    +  console.log(`Server running at http://${hostname}:${port}/`);
    +});
    +
    +
    + +

    Đoạn mã import mô-đun "http" và dùng nó để tạo một server (createServer()) lắng nghe HTTP request ở cổng 3000. Sau đó in ra một thông điệp về URL bạn có thể dùng để kiểm tra server. Hàm createServer() nhận tham số là một hàm callback được gọi khi nhận được một HTTP request — nó đơn giản trả về một response với HTTP status code 200 ("OK") và đoạn chữ "Hello World".

    + +
    +

    Ghi chú: Đừng lo lắng nếu bạn không hiểu chính xác việc mà đoạn code thực hiện. Chúng tôi sẽ giải thích rất chi tiết khi chúng ta bắt đầu sử dụng Express!

    +
    +
  2. +
  3. Khởi động server bằng cách điều hướng đến thư mục chứa hellonode.js trong terminal/ command prompt và gọi node với tên script, như sau: +
    >node hellonode.js
    +Server running at http://127.0.0.1:3000/
    +
    +
  4. +
  5. Truy cập vào URL http://127.0.0.1:3000. Nếu mọi thứ hoạt động, trình duyệt sẽ hiển thị dòng chữ "Hello World".
  6. +
+ +

Using NPM

+ +

Next to Node itself, NPM is the most important tool for working with Node applications. NPM is used to fetch any packages (JavaScript libraries) that an application needs for development, testing, and/or production, and may also be used to run tests and tools used in the development process. 

+ +
+

Note: From Node's perspective, Express is just another package that you need to install using NPM and then require in your own code.

+
+ +

You can manually use NPM to separately fetch each needed package. Typically we instead manage dependencies using a plain-text definition file named package.json. This file lists all the dependencies for a specific JavaScript "package", including the package's name, version, description, initial file to execute, production dependencies, development dependencies, versions of Node it can work with, etc. The package.json file should contain everything NPM needs to fetch and run your application (if you were writing a reusable library you could use this definition to upload your package to the npm respository and make it available for other users).

+ +

Adding dependencies

+ +

The following steps show how you can use NPM to download a package, save it into the project dependencies, and then require it in a Node application.

+ +
+

Note: Here we show the instructions to fetch and install the Express package. Later on we'll show how this package, and others, are already specified for us using the Express Application Generator. This section is provided because it is useful to understand how NPM works and what is being created by the application generator.

+
+ +
    +
  1. First create a directory for your new application and navigate into it: +
    mkdir myapp
    +cd myapp
    +
  2. +
  3. Use the npm init command to create a package.json file for your application. This command prompts you for a number of things, including the name and version of your application and the name of the initial entry point file (by default this is index.js). For now, just accept the defaults: +
    npm init
    + +

    If you display the package.json file (cat package.json), you will see the defaults that you accepted, ending with the license.

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC"
    +}
    +
    +
  4. +
  5. Now install Express in the myapp directory and save it in the dependencies list of your package.json file
  6. +
  7. +
    npm install express --save
    + +

    The dependencies section of your package.json will now appear at the end of the package.json file and will include Express.

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC",
    +  "dependencies": {
    +    "express": "^4.16.3"
    +  }
    +}
    +
    +
  8. +
  9. To use the library you call the require() function as shown below in your index.js file. +
    const express = require('express')
    +const app = express();
    +
    +app.get('/', (req, res) => {
    +  res.send('Hello World!')
    +});
    +
    +app.listen(8000, () => {
    +  console.log('Example app listening on port 8000!')
    +});
    +
    + +

    This code shows a minimal "HelloWorld" Express web application. This imports the "express" module and uses it to create a server (app) that listens for HTTP requests on port 8000 and prints a message to the console explaining what browser URL you can use to test the server. The app.get() function only responds to HTTP GET requests with the specified URL path ('/'), in this case by calling a function to send our Hello World! message. 
    +
    + Create a file named index.js in the root of the "myapp" application directory and give it the contents shown above.

    +
  10. +
  11. You can start the server by calling node with the script in your command prompt: +
    >node index.js
    +Example app listening on port 8000
    +
    +
  12. +
  13. Navigate to the URL (http://127.0.0.1:8000/). If everything is working, the browser should simply display the string "Hello World!".
  14. +
+ +

Development dependencies

+ +

If a dependency is only used during development, you should instead save it as a "development dependency" (so that your package users don't have to install it in production). For example, to use the popular JavaScript Linting tool eslint you would call NPM as shown:

+ +
npm install eslint --save-dev
+ +

The following entry would then be added to your application's package.json:

+ +
  "devDependencies": {
+    "eslint": "^4.12.1"
+  }
+
+ +
+

Note: "Linters" are tools that perform static analysis on software in order to recognise and report adherence/non-adherance to some set of coding best practice.

+
+ +

Running tasks

+ +

In addition to defining and fetching dependencies you can also define named scripts in your package.json files and call NPM to execute them with the run-script command. This approach is commonly used to automate running tests and parts of the development or build toolchain (e.g., running tools to minify JavaScript, shrink images, LINT/analyse your code, etc).

+ +
+

Note: Task runners like Gulp and Grunt can also be used to run tests and other external tools.

+
+ +

For example, to define a script to run the eslint development dependency that we specified in the previous section we might add the following script block to our package.json file (assuming that our application source is in a folder /src/js):

+ +
"scripts": {
+  ...
+  "lint": "eslint src/js"
+  ...
+}
+
+ +

To explain a little further, eslint src/js is a command that we could enter in our terminal/command line to run eslint on JavaScript files contained in the src/js directory inside our app directory. Including the above inside our app's package.json file provides a shortcut for this command — lint.

+ +

We would then be able to run eslint using NPM by calling:

+ +
npm run-script lint
+# OR (using the alias)
+npm run lint
+
+ +

This example may not look any shorter than the original command, but you can include much bigger commands inside your npm scripts, including chains of multiple commands. You could identify a single npm script that runs all your tests at once.

+ +

Installing the Express Application Generator

+ +

The Express Application Generator tool generates an Express application "skeleton". Install the generator using NPM as shown (the -g flag installs the tool globally so that you can call it from anywhere):

+ +
npm install express-generator -g
+ +

To create an Express app named "helloworld" with the default settings, navigate to where you want to create it and run the app as shown:

+ +
express helloworld
+ +
+

Note: You can also specify the template library to use and a number of other settings. Use the help command to see all the options:

+ +
express --help
+
+ +

 

+
+ +

NPM will create the new Express app in a sub folder of your current location, displaying build progress on the console. On completion, the tool will display the commands you need to enter to install the Node dependencies and start the app.

+ +
+

The new app will have a package.json file in its root directory. You can open this to see what dependencies are installed, including Express and the template library Jade:

+ +
{
+  "name": "helloworld",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www"
+  },
+  "dependencies": {
+    "body-parser": "~1.18.2",
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.15.5",
+    "jade": "~1.11.0",
+    "morgan": "~1.9.0",
+    "serve-favicon": "~2.4.5"
+  }
+}
+ +

 

+
+ +

Install all the dependencies for the helloworld app using NPM as shown:

+ +
cd helloworld
+npm install
+
+ +

Then run the app (the commands are slightly different for Windows and Linux/macOS), as shown below:

+ +
# Run the helloworld on Windows with Command Prompt
+SET DEBUG=helloworld:* & npm start
+
+# Run the helloworld on Windows with PowerShell
+SET DEBUG=helloworld:* | npm start
+
+# Run helloworld on Linux/macOS
+DEBUG=helloworld:* npm start
+
+ +

The DEBUG command creates useful logging, resulting in an output like that shown below.

+ +
>SET DEBUG=helloworld:* & npm start
+
+> helloworld@0.0.0 start D:\Github\expresstests\helloworld
+> node ./bin/www
+
+  helloworld:server Listening on port 3000 +0ms
+ +

Open a browser and navigate to http://127.0.0.1:3000/ to see the default Express welcome page.

+ +

Express - Generated App Default Screen

+ +

We'll talk more about the generated app when we get to the article on generating a skeleton application.

+ + + +

Summary

+ +

You now have a Node development environment up and running on your computer that can be used for creating Express web applications. You've also seen how NPM can be used to import Express into an application, and also how you can create applications using the Express Application Generator tool and then run them.

+ +

In the next article we start working through a tutorial to build a complete web application using this environment and associated tools.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/vi/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html b/files/vi/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html new file mode 100644 index 0000000000..6d5192d404 --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html @@ -0,0 +1,135 @@ +--- +title: Kiểm soát luồng không đồng bộ bằng cách sử dụng async +slug: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +--- +

Mã điều khiển cho một số trang LocalLibrary của chúng tôi sẽ phụ thuộc vào kết quả của nhiều yêu cầu bất đồng bộ, có thể được yêu cầu chạy theo một số thứ tự cụ thể hoặc song song. Để quản lý kiểm soát dòng chảy, và đưa ra trang khi chúng tôi có tất cả các thông tin cần thiết có sẵn, chúng tôi sẽ sử dụng các nút phổ biến async module.

+ +
+

Lưu ý: Có một số cách khác để quản lý hành vi bất đồng bộ và kiểm soát luồng trong JavaScript, bao gồm các tính năng ngôn ngữ JavaScript tương đối gần đây như Promises.

+
+ +

Async có rất nhiều phương pháp hữu ích (xem tài liệu ). Một số chức năng quan trọng hơn là:

+ + + +

Tại sao nó cần thiết?

+ +

Hầu hết các phương thức chúng tôi sử dụng trong Express đều bất đồng bộ — bạn chỉ định một thao tác để thực hiện, chuyển một cuộc gọi lại. Phương thức trả về ngay lập tức và gọi lại được gọi khi hoạt động được yêu cầu hoàn tất. Theo quy ước trong Express , hàm gọi lại truyền giá trị lỗi làm tham số đầu tiên (hoặc nullthành công) và kết quả từ hàm (nếu có) làm tham số thứ hai.

+ +

Nếu một bộ điều khiển chỉ cần thực hiện một thao tác bất đồng bộ để có được thông tin cần thiết để hiển thị một trang thì việc triển khai thực hiện rất dễ dàng — chúng tôi chỉ cần hiển thị mẫu trong cuộc gọi lại. Đoạn mã dưới đây cho thấy điều này cho một hàm làm cho số đếm của một mô hình SomeModel(sử dụng count()phương thức Mongoose ):

+ +
exports.some_model_count = function(req, res, next) {
+
+  SomeModel.count ({a_model_field: 'match_value'}, hàm (err, count) {
+    // ... làm gì đó nếu có lỗi
+
+    // Khi thành công, trả kết quả bằng cách chuyển số đếm vào hàm render (ở đây, dưới dạng biến 'data').
+    res.render ('the_template', {data: count});
+  });
+}
+
+ +

Tuy nhiên, nếu bạn cần thực hiện nhiều truy vấn bất đồng bộ và bạn không thể hiển thị trang cho đến khi tất cả các thao tác đã hoàn tất? Việc triển khai ngây thơ có thể "chuỗi daisy" các yêu cầu, khởi động các yêu cầu tiếp theo trong cuộc gọi lại của yêu cầu trước đó và hiển thị phản hồi trong cuộc gọi lại cuối cùng. Vấn đề với cách tiếp cận này là các yêu cầu của chúng tôi sẽ phải được chạy theo chuỗi, mặc dù nó có thể hiệu quả hơn để chạy chúng song song. Điều này cũng có thể dẫn đến mã lồng nhau phức tạp, thường được gọi là địa chỉ gọi lại (callback hell) .

+ +

Một giải pháp tốt hơn sẽ là thực hiện tất cả các yêu cầu song song và sau đó có một cuộc gọi lại duy nhất thực hiện khi tất cả các truy vấn đã hoàn thành. Đây là loại hoạt động lưu lượng mà mô-đun Async làm cho dễ dàng!

+ +

Hoạt động bất đồng bộ song song

+ +

Phương pháp async.parallel()này được sử dụng để chạy nhiều hoạt động bất đồng bộ song song.

+ +

Đối số đầu tiên async.parallel()là một tập hợp các hàm bất đồng bộ để chạy (một mảng, đối tượng hoặc có thể lặp lại khác). Mỗi chức năng được truyền callback(err, result)mà nó phải gọi khi hoàn thành với một lỗi err(có thể là null) và một resultsgiá trị tùy chọn .

+ +

Đối số thứ hai tùy chọn  async.parallel()là một cuộc gọi lại sẽ được chạy khi tất cả các hàm trong đối số đầu tiên đã hoàn thành. Gọi lại được gọi với một đối số lỗi và một bộ sưu tập kết quả có chứa các kết quả của các hoạt động bất đồng bộ riêng lẻ. Bộ sưu tập kết quả có cùng kiểu với đối số đầu tiên (tức là nếu bạn truyền một mảng các hàm bất đồng bộ, thì hàm gọi lại cuối cùng sẽ được gọi với một mảng các kết quả). Nếu bất kỳ hàm song song nào báo cáo lỗi thì gọi lại được gọi sớm (với giá trị lỗi).

+ +

Ví dụ dưới đây cho thấy cách thức này hoạt động khi chúng ta truyền một đối tượng làm đối số đầu tiên. Như bạn có thể thấy, các kết quả được trả về trong một đối tượng có cùng tên thuộc tính như các hàm ban đầu được truyền vào.

+ +
async.parallel({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback
+  function(err, results) {
+    // 'results' is now equal to: {one: 1, two: 2, ..., something_else: some_value}
+  }
+);
+ +

Nếu bạn thay vì truyền một mảng các hàm như đối số đầu tiên, kết quả sẽ là một mảng (kết quả thứ tự mảng sẽ khớp với thứ tự ban đầu mà các hàm được khai báo — không phải thứ tự mà chúng đã hoàn thành).

+ +

Các hoạt động bất đồng bộ trong chuỗi

+ +

Phương thức async.series()này được sử dụng để chạy nhiều hoạt động bất đồng bộ theo thứ tự, khi các hàm tiếp theo không phụ thuộc vào đầu ra của các hàm trước đó. Nó cơ bản được khai báo và cư xử theo cùng một cách như async.parallel().

+ +
async.series({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback after the last asynchronous function completes.
+  function(err, results) {
+    // 'results' is now equals to: {one: 1, two: 2, ..., something_else: some_value}
+  }
+);
+ +
+

Lưu ý: Đặc tả ngôn ngữ ECMAScript (JavaScript) nói rằng thứ tự liệt kê một đối tượng là không xác định, vì vậy có thể các hàm sẽ không được gọi theo cùng thứ tự như bạn chỉ định chúng trên tất cả các nền tảng. Nếu thứ tự thực sự quan trọng, thì bạn nên chuyển một mảng thay vì một đối tượng, như hình dưới đây.

+
+ +
async.series([
+  function(callback) {
+    // do some stuff ...
+    callback(null, 'one');
+  },
+  function(callback) {
+    // do some more stuff ...
+    callback(null, 'two');
+  }
+ ],
+  // optional callback
+  function(err, results) {
+  // results is now equal to ['one', 'two']
+  }
+);
+ +

Các hoạt động bất đồng bộ phụ thuộc trong chuỗi

+ +

Phương thức async.waterfall()này được sử dụng để chạy nhiều hoạt động bất đồng bộ theo thứ tự khi mỗi hoạt động phụ thuộc vào kết quả của hoạt động trước đó.

+ +

Hàm gọi lại được gọi bởi mỗi hàm bất đồng bộ chứa nullđối số đầu tiên và kết quả trong các đối số tiếp theo. Mỗi hàm trong chuỗi lấy các đối số kết quả của lần gọi lại trước đó làm tham số đầu tiên, và sau đó là một hàm gọi lại. Khi tất cả các hoạt động được hoàn thành, một cuộc gọi lại cuối cùng được gọi với kết quả của hoạt động cuối cùng. Cách làm việc này là rõ ràng hơn khi bạn xem xét các đoạn mã dưới đây (ví dụ này là từ async tài liệu):

+ +
async.waterfall([
+  function(callback) {
+    callback(null, 'one', 'two');
+  },
+  function(arg1, arg2, callback) {
+    // arg1 now equals 'one' and arg2 now equals 'two'
+    callback(null, 'three');
+  },
+  function(arg1, callback) {
+    // arg1 now equals 'three'
+    callback(null, 'done');
+  }
+], function (err, result) {
+  // result now equals 'done'
+}
+);
+ +

Cài đặt bất đồng bộ

+ +

Cài đặt mô-đun bất đồng bộ bằng cách sử dụng trình quản lý gói NPM để chúng tôi có thể sử dụng nó trong mã của chúng tôi. Bạn làm điều này theo cách thông thường, bằng cách mở một dấu nhắc trong thư mục gốc của dự án LocalLibrary và nhập vào lệnh sau đây:

+ +
npm install async
+ +

Bước tiếp theo

+ + diff --git a/files/vi/learn/server-side/express_nodejs/displaying_data/index.html b/files/vi/learn/server-side/express_nodejs/displaying_data/index.html new file mode 100644 index 0000000000..bdbf433fc3 --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/displaying_data/index.html @@ -0,0 +1,98 @@ +--- +title: 'Express Tutorial Part 5: Displaying library data' +slug: Learn/Server-side/Express_Nodejs/Displaying_data +tags: + - Beginner + - Controller + - Express + - Learn + - NeedsTranslation + - Template + - TopicStub + - View + - nodejs + - pug +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}
+ +

We're now ready to add the pages that display the LocalLibrary website books and other data. The pages will include a home page that shows how many records we have of each model type, and list and detail pages for all of our models. Along the way we'll gain practical experience in getting records from the database, and using templates.

+ + + + + + + + + + + + +
Prerequisites:Complete previous tutorial topics (including Express Tutorial Part 4: Routes and controllers).
Objective:To understand how to use the async module and Pug template language, and how to get data from the URL in our controller functions.
+ +

Overview

+ +

In our previous tutorial articles we defined Mongoose models that we can use to interact with a database and created some initial library records. We then created all the routes needed for the LocalLibrary website, but with "dummy controller" functions (these are skeleton controller functions that just return a "not implemented" message when a page is accessed).

+ +

The next step is to provide proper implementations for the pages that display our library information (we'll look at implementing pages featuring forms to create, update, or delete information in later articles). This includes updating the controller functions to fetch records using our models, and defining templates to display this information to users.

+ +

We will start by providing overview/primer topics explaining how to manage asynchronous operations in controller functions and how to write templates using Pug. Then we'll provide implementations for each of our main "read only" pages with a brief explanation of any special or new features that they use.

+ +

At the end of this article you should have a good end-to-end understanding of how routes, asynchronous functions, views, and models work in practice.

+ +

Displaying library data tutorial subarticles

+ +

The following subarticles go through the process of adding the different features required for us to display the required website pages. You need to read and work through each one of these in turn, before moving on to the next one.

+ +
    +
  1. Asynchronous flow control using async
  2. +
  3. Template primer
  4. +
  5. The LocalLibrary base template
  6. +
  7. Home page
  8. +
  9. Book list page
  10. +
  11. BookInstance list page
  12. +
  13. Date formatting using moment
  14. +
  15. Author list page and Genre list page challenge
  16. +
  17. Genre detail page
  18. +
  19. Book detail page
  20. +
  21. Author detail page
  22. +
  23. BookInstance detail page and challenge
  24. +
+ +

Summary

+ +

We've now created all the "read-only" pages for our site: a home page that displays counts of instances of each of our models, and list and detail pages for our books, book instances, authors, and genres. Along the way we've gained a lot of fundamental knowledge about controllers, managing flow control when using asynchronous operations, creating views using Pug, querying the database using our models, how to pass information to a template from your view, and how to create and extend templates. Those who completed the challenge will also have learned a little about date handling using moment.

+ +

In our next article we'll build on our knowledge, creating HTML forms and form handling code to start modifying the data stored by the site.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/vi/learn/server-side/express_nodejs/index.html b/files/vi/learn/server-side/express_nodejs/index.html new file mode 100644 index 0000000000..8cdfa86487 --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/index.html @@ -0,0 +1,77 @@ +--- +title: Express web framework (Node.js/JavaScript) +slug: Learn/Server-side/Express_Nodejs +tags: + - Beginner + - CodingScripting + - Express + - Express.js + - Intro + - JavaScript + - Learn + - NeedsTranslation + - Node + - Server-side programming + - TopicStub + - node.js +translation_of: Learn/Server-side/Express_Nodejs +--- +
{{LearnSidebar}}
+ +

Express là một web framework phổ biến, được viết bằng JavaScript và chạy trên môi trường Node.js. Mô-đun sẽ giải thích một số lợi ích của framework này, cách để thiết lập môi trường, phát triển cũng như triển khai ứng dụng.

+ +

Điều kiện tiên quyết

+ +

Trước khi bắt đầu với module này, bạn cần có kiến thức về lập trình web phía máy chủ và web framework là gì, bạn có thể đọc: Những bước đầu về lập trình web phía máy chủ. Bạn cũng cần có kiến thức tổng quát về ngôn ngữ lập trình và đặc biệt là JavaScript, nhưng không quá quan trọng để hiểu những khái niệm cốt lõi.

+ +
+

Note: Những trang web có nhiều tài nguyên để học JavaScript về phát triển ở phía client (khách): JavaScriptJavaScript Guide, JavaScript BasicsJavaScript (learning). Những khái niệm cốt lõi và ngôn ngữ JavaScript là tương tự với phát triển ở phía server (chủ) trên Node.js và tài liệu này sẽ đề cập. Node.js cung cấp các APIs bổ sung để hỗ trợ các chức năng hữu ích trong môi trường không có trình duyệt, ví dụ: tạo các máy chủ HTTP và truy cập hệ thống tệp, nhưng không hỗ trợ các JavaScript APIs để làm việc với trình duyệt và DOM.

+ +

Hướng dẫn này sẽ cung cấp một số kiến thức khi làm việc với Node.js và Express, có vô số tài nguyên tuyệt vời khác trên Internet và trong sách — vài trong số đó đến từ How do I get started with Node.js (StackOverflow) và What are the best resources for learning Node.js? (Quora).

+
+ +

Hướng Dẫn

+ +
+
Giới thiệu Express/Node
+
Trong bài viết đầu tiên về Express, chúng ta trả lời câu hỏi "Node là gì?" và "Express là gì?" và cho bạn một cái nhìn tổng quan về thứ làm nên sự đặc biệt của Express web framework. Chúng ta sẽ điểm qua các tính năng chính và cho bạn thấy những thành phần dựng nên một ứng dụng Express (mặc dù hiện tại bạn chưa có môi trường phát triển để thử nó).
+
Cài đặt một môi trường phát triển Node (Express)
+
Bây giờ bạn đã biết Express là gì, chúng ta sẽ xem cách để cài đặt một môi trường Node/Express trên Windows, Linux (Ubuntu), và macOS. Bất kỳ hệ điều hành phổ biến nào bạn đang sử dụng, bài viết này sẽ cho bạn những thứ cần thiết để có thể bắt đầu phát triển ứng dụng Express.
+
Hướng dẫn Express: Trang web Local Library
+
Bài đầu tiên trong chuỗi hướng dẫn thực hành giải thích những gì bạn sẽ học, và tổng quan về ví dụ trang web "local library" mà chúng ta sẽ làm việc và phát triển trong các bài tiếp theo.
+
Hướng dẫn Express Phần 2: Tạo cấu trúc cho dự án
+
Bài này hướng dẫn bạn cách tạo một "bộ khung" cho dự án web, là nơi để bạn tiếp tục phát triển định tuyến (routes) cho các trang, templates/views và cơ sở dữ liệu.
+
Hướng dẫn Express Phần 3: Sử dụng cơ sở dữ liệu (với Mongoose)
+
Bài này giới thiệu tóm tắt về cơ sở dữ liệu cho Node/Express. Sau đó là cách chúng ta sử dụng Mongoose để truy cập cơ sở dữ liệu cho trang web LocalLibrary. Bài viết giải thích cách lược đồ đối tượng và các mô hình được khai báo, các trường chính và xác thực cơ bản, cũng như cho biết một số cách chính để truy cập dữ liệu mô hình.
+
Hướng dẫn Express Phần 4: Routes và controllers
+
Trong phần này chúng ta sẽ thiếp lập định tuyến (code xử lý URL) với các hàm xử lý "?giả" cho các tài nguyên cần thiết trong trang web LocalLibrary. Khi hoàn thành, chúng ta sẽ có một cấu trúc mô-đun để đặt code xử lý định tuyến, sau đó có thể mở rộng bằng các hàm xử lý thật ở các bài sau. Từ đó chúng ta có được hiểu biết tốt về cách tạo mô-đun định tuyến sử dụng Express.
+
Hướng dẫn Express Phần 5: Hiển thị dữ liệu thư viện
+
Bây giờ chúng ta đã sẵn sàng để thêm các trang hiển thị sách và dữ liệu của trang web LocalLibrary. Những trang này gồm một trang chủ để xem có bao nhiêu bản ghi trên mỗi loại mô hình, các trang xem danh sách, chi tiết cho tất cả các mô hình. Chúng ta sẽ thực hành theo cách lấy các bản ghi từ cơ sở dữ liệu và dùng các bản mẫu (templates).
+
Hướng dẫn Express Phần 6: Làm việc với forms
+
Trong bài này chúng ta sẽ xem cách làm việc với HTML Forms trong Express, sử dụng Pug và cách để viết form tạo, cập nhật, xoá tài liệu từ cơ sở dữ liệu.
+
Hướng dẫn Express Phần 7: Triển khai sử dụng
+
Bây giờ bạn đã tạo xong trang web LocalLibrary tuyệt vời, bạn sẽ muốn cài đặt nó lên một máy chủ public để các nhân viên thư viện và các thành viên có thể truy cập được từ Internet. Bài này cung cấp tổng quan về cách làm sao để bạn có thể tìm một máy chủ để triển khai trang web của bạn và những gì bạn cần để giúp trang web sẵn sàng sử dụng.
+
+ +

Xem thêm

+ +
+
Cài đặt LocalLibrary trên PWS/Cloud Foundry
+
Bài này cung cấp một minh họa thực tế cách để cài đặt LocalLibrary trên Pivotal Web Services PaaS cloud — một dịch vụ nguồn mở với đầy đủ tính năng thay thế cho Heroku, dịch vụ cloud PaaS đã sử dụng ở Phần 7 của hướng dẫn bên trên. PWS/Cloud Foundry chắc chắn đáng giá để dùng nếu bạn đang tìm một sự thay thế cho Heroku (hoặc một dịch vụ cloud PaaS khác), hoặc đơn giản là muốn thử một thứ gì đó khác.
+
+ +

Thêm các bài hướng dẫn

+ +
+

Các bài hướng dẫn kết thúc tại đó (đến hiện tại). Nếu bạn muốn mở rộng, các chủ đề thú vị khác để nói đến là:

+ + + +

Và đương nhiên sẽ rất tuyệt nếu có một bài tập đánh giá!

+
diff --git a/files/vi/learn/server-side/express_nodejs/mongoose/index.html b/files/vi/learn/server-side/express_nodejs/mongoose/index.html new file mode 100644 index 0000000000..fdf6531d75 --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/mongoose/index.html @@ -0,0 +1,800 @@ +--- +title: 'Hướng dẫn Express Phần 3: Sử dụng Database (với Mongoose)' +slug: Learn/Server-side/Express_Nodejs/mongoose +translation_of: Learn/Server-side/Express_Nodejs/mongoose +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}
+ +

Bài viết này giới thiệu tổng quan về cơ sở dữ liệu và cách dùng chúng với các ứng dụng Node/Express. Sau đó nó sẽ chỉ cho ta thấy cách sử dụng Mongoose để tạo ra kết nối đến cơ sở dữ liệu cho trang web LocalLibrary. Nó giải thích cách mà schema và model của đối tượng được định nghĩa, các kiểu trường chính, và cách thức xác thực cơ bản. Nó còn trình bày một số cách chính để bạn có thể truy cập tới dữ liệu của model.

+ + + + + + + + + + + + +
Bài viết trước:Express Tutorial Part 2: Creating a skeleton website
Mục tiêu:Có thể thiết kế và tự tạo model của riêng mình thông qua Mongoose.
+ +

Khái quát

+ +

Thủ thư sẽ dùng trang web Local Library để lưu trữ thông tin về sách và người mượn, trong khi các bạn đọc sẽ dùng nó để kiếm sách, tìm xem có bao nhiêu cuốn có sẵn, và tiếp tục như thế hoặc làm thủ tục mượn sách. Để có thể lưu trữ và truy xuất thông tin một cách hiệu quả, ta sẽ lưu trữ tất cả trong một cơ sở dữ liệu.

+ +

Các ứng dụng Express có thể dùng nhiều loại cơ sở dữ liệu khác nhau, và có khá là nhiều hướng tiếp cận để bạn có thể thi hành Create, Read, Update and Delete (CRUD). Bài viết này sẽ cung cấp khái quát một số lựa chọn có thể áp dụng, và sẽ đi vào phân tích một phương pháp nhất định.

+ +

Tôi có thể dùng cơ sở dữ liệu nào?

+ +

Ứng dụng Express có thể dùng bất cứ cơ sở dữ liệu nào được hỗ trợ bởi Node (Chính Express không đưa ra bất cứ đặc tả chỉ tiết hành vi hay ràng buộc nào về hệ quản trị cơ sở dữ liệu). Thành ra có rất nhiều thứ để bạn thoả sức chọn lựa, bao gồm PostgreSQL, MySQL, Redis, SQLite, và MongoDB.

+ +

Khi chọn một cơ sở dữ liệu, bạn nên cân nhắc những thứ như là độ khó, hiệu năng, dễ dàng bảo trì, chi phí, sự hỗ trợ của cộng đồng, vân vân và mây mây. Do chưa có cơ sở dữ liệu nào đạt được danh hiệu 'tốt nhất', nên ta có thể lựa chọn hầu như mọi giải pháp vừa kể trên cho một trang cỡ nhỏ tới vừa như trang Local Library của chúng ta.

+ +

Để biết thêm chi tiết để tiện đường lựa chọn: Database integration (Tài liệu của Express).

+ +

Cách nào tốt nhất để thao tác với cơ sở dữ liệu?

+ +

Có hai hướng tiếp cận để tương tác với một cơ sở dữ liệu: 

+ + + +

Sử dụng ngôn ngữ truy vấn được hỗ trợ bởi cơ sở dữ liệu (như là SQL) sẽ đạt được hiệu suất cao nhất. ODM thường chậm hơn bởi nó phải thông dịch mã để có thể truy vấn giữa đối tượng và định dạng của cơ sở dữ liệu, mà không dùng được các truy vấn hiệu quả nhất của cơ sở dữ liệu (điều này càng nghiêm trọng hơn khi ORM được sử dụng cho nhiều dạng cơ sở dữ liệu khác nhau, và phải tạo ra nhiều điều khoản lằng nhằng hơn đối với lượng tính năng được cơ sở dữ liệu hỗ trợ).

+ +

Điểm mạnh của ORM là lập trình viên có thể giữ tư duy như với đối tượng của JavaScript thay vì phải ngôn ngữ thuần tuý viết riêng cho cơ sở dữ liệu — điều này càng đúng khi bạn phải làm việc với nhiều loại cơ sở dữ liệu (trên cùng hoặc khác trang web). ORM còn cung cấp các tính năng để thực hiện xác thực và kiểm tra dữ liệu.

+ +
+

Mẹo:  Sử dụng ODM/ORMs thường giúp giảm thiểu chi phí phát triển và bảo trì! Trừ khi bạn đã quá thân thuộc với ngôn ngữ truy vấn thuần tuý hoặc hiệu suất là trên hết, bạn nên cân nhắc đến việc sử dụng ODM.

+
+ +

Tôi nên dùng ORM/ODM nào?

+ +

Có nhiều giải pháp cho ODM/ORM có sẵn trên trang quản lý gói NPM (tìm theo nhãn odm và orm!).

+ +

Vào thời điểm viết bài này có một số giải pháp phổ biến như sau:

+ + + +

Như một luật ngầm định, bạn nên cân nhắc cả tính năng được công bố cũng như "hoạt động cộng đồng" (tải xuống, sự đóng góp, báo lỗi, chất lượng của tài liệu, vân vân và mây mây) khi lựa chọn một giải pháp. Vào thời điểm viết bài thì Mongoose là một ORM phổ biến nhất, và là lựa chọn hợp lý nếu bạn dùng MongoDB làm cơ sở dữ liệu của mình.

+ +

Sử dụng Mongoose và MongoDb cho LocalLibrary

+ +

Đối với ví dụ Local Library (và cho cả phần còn lại của bài viết này) ta sẽ sử dụng Mongoose ODM để truy cập dữ liệu thư viện của chúng ta. Mongoose hoạt động như một frontend của MongoDB, cơ sở dữ liệu mở dạng NoSQL sử dụng mô hình dữ liệu hướng document. Một “collection” và “documents”, trong cơ sở dữ liệu MongoDB, tương tự với một “table” và “row” trong cơ sở dữ liệu quan hệ.

+ +

ODM và kết hợp cơ sở dữ liệu này cực kì phổ biến trong cộng đồng Node, phần lớn là bởi kho chứa document và hệ thống truy vấn khá là giống với JSON, vã dĩ nhiên rất đỗi thân quen với các lập trình viên JavaScript.

+ +
+

Mẹo: Bạn không cần phải biết gì về MongoDB để có thể sử dụng được Mongoose, mặc dù vài phần trong tài liệu của Mongoose sẽ dễ đọc hiểu hơn nếu bạn đã quen với MongoDB rồi.

+
+ +

Phần còn lại của bài viết này hướng dẫn cách để định nghĩa và truy cập schema và model của Mongoose thông qua ví dụ làm trang web cho LocalLibrary.

+ +

Thiết kế model LocalLibrary

+ +

Trước khi nhảy bổ vào viết code cho model, sẽ tốt hơn nếu ta dành vài phút để nghĩ về dữ liệu ta cần phải lưu trữ và mối quan hệ giữa các đối tượng khác nhau.

+ +

Chúng ta biết rằng chúng ta cần phải lữu trữ dữ liệu về sách (tựa đề, tóm tắt, tác giả, thể loại, mã số tiêu chuẩn quốc tế cho sách) và sẽ có khá nhiều cuốn giống nhau (với mã số quốc tế riêng biệt, tình trạng, vân vân.). Có lẽ ta sẽ cần lưu trữ nhiều thông tin về tác giả hơn chỉ là tên của người đó, và có vô số tác giả trùng hoặc có tên na ná nhau. Chúng ta muốn phân loại thông tin dựa theo tựa đề, tác giả, thể loại, và kiểu sách.

+ +

Công cuộc thiết kế model yêu cầu thiết kế các mô hình riêng rẽ cho từng "object" (nhóm các thông tin có liên quan với nhau). Trong trường hợp này thì các object ấy hẳn là sách, các thuộc tính của sách, và tác giả.

+ +

Bạn chắc hẳn sẽ muốn biểu diễn mô hình dưới dạng danh sách liệt kê (ví dụ như một danh sách các lựa chọn), thay vì code cứng tất tần tật — việc này được đề nghị khi các lựa chọn vẫn chưa được liệt kê hết hoặc có thể bị thay đổi. Ứng viên sáng giá cho việc mô hình hoá này chính là thể loại sách (ví dụ như Khoa học Viễn tưởng, Ngôn tình, hoặc gì đó tương tự.)

+ +

Khi đã quyết định được các mô hình và trường dữ liệu, ta cần phải suy ngẫm về mối quan hệ giữa chúng.

+ +

Để làm tốt việc này, ta sẽ dùng biểu đồ liên hệ UML như bên dưới để biểu diễn các model ta sắp định nghĩa ra (trong các hộp). Như đã nói ở trên, ta vừa tạo ra model cho sách (chi tiết cơ bản nhất cho sách), phần tử của sách (lượng bản sách còn trong hệ thống), và tác giả. Chúng ta cũng vừa quyết định sẽ tạo thêm model cho thể loại, để giá trị của nó thay đổi động. Ta cũng vừa quyết định sẽ không tạo mô hình cho BookInstance:status — chúng ta sẽ code cứng phần này đến một giá trị có thể chấp nhận được bởi ta không mong muốn giá trị của nó bị thay đổi. Bạn có thể thấy trong mỗi hộp là tên của mô hình, tên của các trường và kiểu dữ liệu tương ứng, đồng thời cả các thuộc tính và kiểu trả về nữa.

+ +

Biểu đồ còn chỉ ra mối quan hệ giữa các mô hình, bao gồm cả bội số. Bội số là các con số nhỏ nhỏ nằm trên các đường thẳng nối các hộp lại với nhau (lớn nhất và nhỏ nhất) để chỉ ra độ liên hệ trong các mối quan hệ giữa các mô hình với nhau. Láy ví dụ như trong hình dưới, những đoạn kẻ nối giữa các hộp biểu diễn rằng Book và Genre liên quan đến nhau. Con số nằm gần với mô hình Book chỉ ra rằng Book phải có từ 0 đến nhiều Genre (bao nhiêu tuỳ thích), trong khi con số nằm ở đầu đoạn bên kia của Genre lại chỉ ra rằng nó có 0 hoặc nhiều liên hệ với Book.

+ +
+

Lưu ý: Như đã nói trong Mongoose primer phía dưới, thường sẽ tốt hơn nếu có một trường riêng để định nghĩa mối quan hệ giữa documents/models chỉ trong một mô hình (bạn vẫn có thể tìm thấy mối quan hệ ngược lại bằng cách tìm kiếm _id liên quan trong các mô hình khác). Bên dưới biểu diễn mối quan hệ giữa Book/Genre and Book/Author trong Book schema, và mối quan hệ giữa Book/BookInstance trong BookInstance Schema. Việc lựa chọn này hơi cảm tính — ta hoàn toàn có thể định nghĩa các trường trong một schema khác.

+
+ +

Mongoose Library Model  with correct cardinality

+ +
+

Lưu ý: Phần tiếp theo cung cấp kiến thức cơ bản giải thích cách mô hình được định nghĩa và sử dụng. Ta sẽ tìm cách để xây dựng đống mô hình vừa vẽ ra trong biểu đồ trên.

+
+ +

Mongoose primer

+ +

Phần này giới thiệu khái quát cách để kết nối Mongoose với một cơ sở dữ liệu MongoDB, cách định nghĩa một schema và một model, và cách viết vài câu truy vấn đơn giản. 

+ +
+

Lưu ý: Cái primer này "bị ảnh hưởng mạnh" bởi Mongoose quick start trên npm và official documentation.

+
+ +

Cài đặt Mongoose và MongoDB

+ +

Mongoose được cài đặt vào trong project của bạn (package.json) giống hệt như các dependency khác — dùng NPM. Để cài đặt nó, chạy câu lệnh sau trong thư mục project của bạn:

+ +
npm install mongoose
+
+ +

Sau khi cài xong, Mongoose sẽ tự động thêm mọi dependencies của nó, bao gồm cả driver cơ sở dữ liệu cho MongoDB, nhưng nó sẽ không cài đặt MongoDB đâu nhé. Nếu bạn muốn cài đặt một máy chủ MongoDB thì bạn có thể tải xuống bộ cài tại đây, dành cho nhiều vô số hệ điều hành khác nhau và cài đặt nó trên hệ thống của mình. Bạn cũng có thể sử dụng MongoDB trên đám mây.

+ +
+

Lưu ý: Trong bài viết này, ta sẽ sử dụng mLab, một cơ sở dữ liệu được cung cấp dưới dạng dịch vụ trên nền tảng điện toán đám mây và chọn sandbox tier nhé. Cái này khá hợp với khâu phát triển, và không phụ thuộc vào việc "cài đặt" hệ điều hành (cơ-sở-dữ-liệu-cung-cấp-dưới-dạng-dịch-vụ là một hướng tiếp cận nếu sử dụng trong dự án thật).

+
+ +

Kết nối với MongoDB

+ +

Mongoose yêu cầu một kết nối tới cơ sở dữ liệu MongoDB. Bạn có thể require() và kết nối cục bộ tới cơ sở dữ liệu thông qua mongoose.connect(), như bên dưới.

+ +
//Nhập mô-đun mongoose
+var mongoose = require('mongoose');
+
+//Thiết lập một kết nối mongoose mặc định
+var mongoDB = 'mongodb://127.0.0.1/my_database';
+mongoose.connect(mongoDB);
+//Ép Mongoose sử dụng thư viện promise toàn cục
+mongoose.Promise = global.Promise;
+//Lấy kết nối mặc định
+var db = mongoose.connection;
+
+//Ràng buộc kết nối với sự kiện lỗi (để lấy ra thông báo khi có lỗi)
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

Bạn có thể lấy ra đối tượng mặc định Connection với mongoose.connection. Ngay khi đã kết nối, sự kiện sẽ nổ ra trên thuộc tính Connection.

+ +
+

Mẹo: Nếu bạn muốn thêm mới các kết nối khác thì có thể dùng mongoose.createConnection(). Vẫn dùng chung định dạng URI (bao gồm máy chủ, cơ sở dữ liệu, cổng, lựa chọn khác.) như connect() và trả về một đối tượng Connection).

+
+ +

Định nghĩa và tạo ra các model

+ +

Model được định nghĩa thông qua giao diện Schema. Schema định nghĩa các trường được lưu trong mỗi document đi kèm với điều kiện xác thực và giá trị mặc định cho chúng. Hơn nữa, bạn có thể khởi tạo các thuộc tính tĩnh và phương thức hỗ trợ để làm việc với kiểu dữ liệu của bạn dễ dàng hơn, và cả các đặc tính ảo để có thể dùng như bất cứ trường nào, mà không bị lưu vào trong cơ sở dữ liệu (ta sẽ bàn về vấn đề này sau).

+ +

Schema sau đó được "biên dịch" thành mô hình qua phương thức mongoose.model(). Một khi đã có mô hình thì bạn có thể dùng nó để tìm, thêm, sửa, và xoá các đối tượng cùng kiểu.

+ +
+

Lưu ý: Mỗi mô hình có liên kết tới một bộ sưu tập các tài liệu trong cơ sở dữ liệu MongoDB. Documents sẽ chứa các trường/kiểu schema được định nghĩa trong mô hình Schema.

+
+ +

Định nghĩa schema

+ +

Đoạn code bên dưới trình bày cách cách thức tạo ra một Schema đơn giản. Đầu tiên bạn require() mongoose, rồi dùng phương thức khởi tạo của Schema để tạo ra một biến schema, định nghĩa một vài trường trong tham số truyền vào của phương thức khởi tạo.

+ +
//Require Mongoose
+var mongoose = require('mongoose');
+
+//Định nghĩa một schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+    a_string: String,
+    a_date: Date
+});
+
+ +

Trong trường hợp trên ta chỉ có 2 trường, một string và một date. Trong phần tiếp theo, ta sẽ thêm một vài trường khác, xác thực, và một số phương thức khác.

+ +

Thêm mới một mô hình

+ +

Mô hình được tạo ra từ schema qua phương thức mongoose.model():

+ +
// Định nghĩa schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+    a_string: String,
+    a_date: Date
+});
+
+// Biên dịch mô hình từ schema
+var SomeModel = mongoose.model('SomeModel', SomeModelSchema );
+ +

Tham số thứ nhất là tên riêng cho collection sắp được tạo ra cho mô hình của bạn (Mongoose sẽ khởi tạo một collection cho model SomeModel ở phía trên), và tham số thứ hai là schema mà bạn muốn dùng để tạo ra mô hình.

+ +
+

Lưu ý: Khi đã có các model class, bạn có thể sử dụng chúng để thêm, sửa, hoặc xoá các bản ghi, và để chạy các câu truy vấn lấy tất cả các bản ghi hoặc tạo các tập hợp con cho một số lượng bản ghi nhất định. Ta sẽ tìm hiểu việc này trong phần Sử dụng mô hình, và khi ta tạo khung nhìn.

+
+ +

Kiểu Schema (các trường)

+ +

Một schema có thể có số trường thông tin tuỳ ý — mỗi trường đại diện cho một document lưu trong MongoDB. Schema trong ví dụ bên dưới trình bày các kiểu đơn giản của các trường cũng như cách định nghĩa chúng.

+ +
var schema = new Schema(
+{
+  name: String,
+  binary: Buffer,
+  living: Boolean,
+  updated: { type: Date, default: Date.now },
+  age: { type: Number, min: 18, max: 65, required: true },
+  mixed: Schema.Types.Mixed,
+  _someId: Schema.Types.ObjectId,
+  array: [],
+  ofString: [String], // Bạn có thể tạo mảng cho các trường khác
+  nested: { stuff: { type: String, lowercase: true, trim: true } }
+})
+ +

Hầu hết các SchemaTypes (đống miêu tả sau từ “type:” hoặc sau tên trường) đều tự định nghĩa chính nó. Ngoại trừ:

+ + + +

Đoạn code cũng chỉ ra hai cách để khai báo một trường:

+ + + +

Để biết thêm chi tiết, mời bạn xem thêm SchemaTypes (Tài liệu của Mongoose).

+ +

Xác thực

+ +

Mongoose cung cấp một số hàm xác thực định sẵn và tuỳ chỉnh, và các hàm xác thực đồng bộ cũng như bất đồng bộ. Nó cho phép bạn đặc tả cả phạm vi chấp nhận hoặc giá trị và thông báo lỗi khi hàm xác thực gặp phải sự cố trong mọi trường hợp.

+ +

Các hàm xác thực định sẵn bao gồm:

+ + + +

Ví dụ bên dưới (hơi khác một chút so với tài liệu của Mongoose) chỉ ra cách để thêm các hàm xác minh và thông báo lỗi:

+ +

+    var breakfastSchema = new Schema({
+      eggs: {
+        type: Number,
+        min: [6, 'Too few eggs'],
+        max: 12
+        required: [true, 'Why no eggs?']
+      },
+      drink: {
+        type: String,
+        enum: ['Coffee', 'Tea', 'Water',]
+      }
+    });
+
+ +

Để biết thêm thông tin chi tiết về các hàm xác minh, hãy vào Validation (tài liệu của Mongoose) để tìm đọc.

+ +

Thuộc tính ảo

+ +

Thuộc tính ảo là các thuộc tính của document mà bạn có thể lấy ra và đặt lại mà không làm ảnh hưởng tới MongoDB. Hàm lấy ra hiệu quả cho việc định dạng lại hoặc kết hợp các trường, trong khi hàm đặt lại lại hữu dụng cho việc phân tách một giá trị riêng lẻ thành nhiều giá trị trong cơ sở dữ liệu. Ví dụ trong tài liệu khởi tạo (và huỷ tạo) một thuộc tính ảo tên đầy đủ từ trường họ và tên, điều đó sẽ dễ dàng và sạch sẽ hơn thay vì tạo ra một trường họ tên mỗi khi có ai đó sử dụng mẫu.

+ +
+

Lưu ý: Ta sẽ dùng thuộc tính ảo trong thư viện để định nghĩa một URL đặc trưng cho từng bản ghi của mô hình thông qua một đường dẫn và giá trị của mỗi bản ghi _id của mỗi bản ghi.

+
+ +

Để biết thêm chi tiết hãy vào Virtuals (tài liệu của Mongoose).

+ +

Phương thức và câu truy vấn trợ giúp

+ +

Một schema có thể còn có phương thức biến, phương thức tĩnh, và hỗ trợ truy vấn. Phương thức biến và phương thức tĩnh gần như tương tự nhau, điểm khác biệt duy nhất là phương thức tĩnh liên kết với một bản ghi xác định và có quyền truy cập tới đối tượng hiện tại. Hỗ trợ truy vấn cho phép bạn mở rộng chainable query builder API của mongoose (ví dụ như, cho phép bạn thêm câu truy vấn "byName" sau các phương thức find(), findOne() và findById()).

+ +

Sử dụng mô hình

+ +

Ngay khi đã có một schema, bạn có thể dùng nó để tạo ra các mô hình. Mô hình đại diện cho một bộ sưu tập các tài liệu trong cơ sở dữ liệu mà bạn có thể tìm kiếm, trong khi các phần tử của mô hình đại diện cho từng tài liệu mà bạn có thể lưu trữ và truy xuất.

+ +

Chúng ta chỉ có thể tìm hiểu sơ qua như trên thôi. Nếu muốn chi tiết hơn thì hãy vào xem: Models (tài liệu của Mongoose).

+ +

Thêm mới và chỉnh sửa tài liệu

+ +

Để thêm mới một bản ghi, bạn có thể định nghĩa một phần tử của mô hình và sau đó dùng lời gọi save(). Ví dụ bên dưới chỉ ra rằng SomeModel là một đối tượng (chỉ có một trường là "name") mà ta vừa tạo ra từ schema của mình.

+ +
// Thêm mới một phần tử của mô hình SomeModel
+var awesome_instance = new SomeModel({ name: 'awesome' });
+
+// Lưu phần tử vừa thêm mới lại, thông qua việc truyền vào một hàm callback
+awesome_instance.save(function (err) {
+  if (err) return handleError(err);
+  // saved!
+});
+
+ +

Việc thêm bản ghi (đi kèm với sửa, xoá, và tìm kiếm) là các công việc bất đồng bộ — bạn phải truyền vào một hàm callback sau khi công việc hoàn tất. API sử dụng quy ước lỗi-trước, thế nên tham số thứ nhất trong hàm callback luôn là một giá trị lỗi (hoặc null). Nếu API trả về kết quả nào đó, nó sẽ được truyền vào qua tham số thứ hai.

+ +

Bạn cũng có thể sử dụng create() để vừa định nghĩa một phần tử của mô hình vừa lưu lại nó luôn. Hàm callback sẽ trả về một lỗi ứng với tham số thứ nhất và phần tử của mô hình vừa khởi tạo qua tham số thứ hai.

+ +
SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) {
+  if (err) return handleError(err);
+  // lưu!
+});
+ +

Mỗi mô hình đều có một kết nối liên quan  (kết nối sẽ mặc định nếu dùng lệnh mongoose.model()). Bạn thêm mới một kết nối và gọi lệnh .model() để tạo thêm tài liệu trên một cơ sở dữ liệu khác.

+ +

Bạn có thể truy cập vào trường của bản ghi mới thông qua cú pháp chấm (.) , và thay đổi giá trị ở trong. Bạn sẽ phải gọi save() hoặc update() để lưu lại giá trị vừa chỉnh sửa vào cơ sở dữ liệu.

+ +
// Truy cập vào trường dữ liệu của bản ghi qua cú pháp (.)
+console.log(awesome_instance.name); //sẽ in ra 'also_awesome'
+
+// Thay đổi bản ghi bằng cách chỉnh sửa trường thông tin, sau đó gọi lệnh save().
+awesome_instance.name="New cool name";
+awesome_instance.save(function (err) {
+   if (err) return handleError(err); // lưu!
+   });
+
+ +

Tìm kiếm các bản ghi

+ +

Bạn có thể tìm kiếm các bản ghi bằng các phương thức truy vấn, viết các câu truy vấn như đối với một tài liệu JSON. Đoạn code phía dưới trình bày cách tìm kiếm các vận động viên chơi ten-nít trong cơ sở dữ liệu, chỉ trả về các trường như tên và tuổi của vận động viên. GIờ ta sẽ chỉ xác định ra một trường (thể thao) bạn có thể thêm bao nhiêu tiêu chí tuỳ ý, xác định thêm các tiêu chí với regex, hoặc loại bỏ tất cả các điều kiện để trả về tất cả các vận động viên.

+ +
var Athlete = mongoose.model('Athlete', yourSchema);
+
+// tìm tất cả các vận động viên chơi tennis, chọn hai trường 'name' và 'age'
+Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) {
+  if (err) return handleError(err);
+  // 'athletes' chứa danh sách các vận động viên phù hợp với tiêu chí đã đề ra.
+})
+ +

Nếu bạn ném vào môt hàm callback, như ở trên, câu truy vấn sẽ được thực thi ngay lập tức. Hàm callback sẽ được gọi khi câu truy vấn hoàn tất.

+ +
+

Lưu ý: Tất cả các hàm callback trong Mongoose sử dụng mẫu callback(error, result). Nếu có lỗi xảy ra khi thực hiện câu truy vấn, tham số error sẽ chứa tất cả các lỗi, và result sẽ trở thành null. Nếu câu truy vấn hợp lệ, tham số error sẽ trở thành null, và result sẽ chứa đựng kết quả của câu truy vấn.

+
+ +

Nếu bạn không truyền vào một hàm callback nào thì API sẽ trả về một giá trị kiểu Query. Bạn có thể sử dụng đối tượng query này để kéo dài câu truy vấn trước khi thực thi nó (thông qua việc truyền vào một hàm callback) sau sử dụng phương thức exec().

+ +
// tìm kiếm tất cả các vận động viên
+var query = Athlete.find({ 'sport': 'Tennis' });
+
+// chọn ra hai trường 'name' và 'age'
+query.select('name age');
+
+// giới hạn kết quả lại 5 bản ghi
+query.limit(5);
+
+// sắp xếp theo tên
+query.sort({ age: -1 });
+
+// thực thi câu truy vấn
+query.exec(function (err, athletes) {
+  if (err) return handleError(err);
+  // athletes chứa một danh sách 5 vận động viên chơi tennis được xếp theo tên
+})
+ +

Ở trên ta đưa tất cả điều kiện truy vấn vào trong phương thức find(). Thay vì vậy ta cũng có thể sử dụng hàm where(), và ta có thể xâu chuỗi các lời gọi bằng cú pháp chấm (.) thay vì phải gọi từng câu riêng rẽ. Đoạn code phía dưới làm y chang phần trên, thêm vài điều kiện cho trường tuổi.

+ +
Athlete.
+  find().
+  where('sport').equals('Tennis').
+  where('age').gt(17).lt(50).  //Điều kiện thêm vào sau hàm where
+  limit(5).
+  sort({ age: -1 }).
+  select('name age').
+  exec(callback); // callback ở đây là tên hàm callback của ta.
+ +

Phương thức find() lấy ra tất cả các bản ghi thoả mãn điều kiện, nhưng thường thì bạn chỉ muốn lấy ra một thôi. Các phương thức truy vấn phía dưới chỉ lấy ra một bản ghi:

+ + + +
+

Lưu ý: Còn có phương thức count() để đếm số lượng bản ghi phù hợp với điều kiện đề ra. Cái này sẽ có ích nếu bạn chỉ cần tìm ra số lượng thay vì phải kéo về tất cả các bản ghi.

+
+ +

Còn có nhiều thứ nữa mà bạn có thể làm với các câu truy vấn. Để biết thêm thông tin mời xem: Queries (tài liệu Mongoose).

+ +

Làm việc với tài liệu liên quan — sự cư ngụ

+ +

Bạn có thể thêm mới mối liên quan giữa các tài liệu/phần tử của mô hình qua trường schema ObjectId, hoặc từ một tài liệu đến nhiều qua một mảng ObjectIds. Trường này lưu trữ id của mô hình liên quan. Nếu bạn muốn lấy nội dung của tài liệu liên quan, bạn có thể sử dụng phương thức populate() trong câu truy vấn để thay thế id với đống dữ liệu tương ứng.

+ +

Chẳng hạn, schema sau đây định nghĩa tác giả và tác phẩm. Mỗi tác giả có thể có nhiều tác phẩm, nên ta sử dụng một mảng đối tượng ObjectId. Mỗi tác phẩm có thể có một tác giả. Thuộc tính "ref" (được in đậm) kể cho ta biết schema nào mà model có thể gắn vào được.

+ +
var mongoose = require('mongoose')
+  , Schema = mongoose.Schema
+
+var authorSchema = Schema({
+  name    : String,
+  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
+});
+
+var storySchema = Schema({
+  author : { type: Schema.Types.ObjectId, ref: 'Author' },
+  title    : String
+});
+
+var Story  = mongoose.model('Story', storySchema);
+var Author = mongoose.model('Author', authorSchema);
+ +

Ta có thể lưu lại đống liên quan đến tài liệu tương ứng bằng cách gán cho nó giá trị _id. Đoạn bên dưới ta tạo ra một tác giả, rồi một cuốn sách và gắn id của tác giả vào trường tác giả của tác phẩm.

+ +
var bob = new Author({ name: 'Bob Smith' });
+
+bob.save(function (err) {
+  if (err) return handleError(err);
+
+  //Bob giờ đã tồn tại, đến lúc tạo tác phẩm rồi
+  var story = new Story({
+    title: "Bob goes sledding",
+    author: bob._id    // gắn _id của tác giả Bob. ID này được tạo ra mặc định!
+  });
+
+  story.save(function (err) {
+    if (err) return handleError(err);
+    // Bob giờ đã có tác phẩm của mình
+  });
+});
+ +

Tài liệu tác phẩm của ta giờ được nối với trường tác giả thông qua ID của trong tài liệu tác giả. Để lấy thông tin của tác giả ta dùng hàm populate(), như bên dưới.

+ +
Story
+.findOne({ title: 'Bob goes sledding' })
+.populate('author') //Thay thế ID của tác giả bằng thông tin của tác giả!
+.exec(function (err, story) {
+  if (err) return handleError(err);
+  console.log('The author is %s', story.author.name);
+  // in ra "The author is Bob Smith"
+});
+ +
+

Lưu ý: Ta vừa thêm tác giả vào tác phẩm, nhưng lại không hề thêm tác phẩm vào mảng stories của tác giả. Thế thì làm thế nào để lấy ra tất cả tác phẩm của một tác giả nào đó? Có một cách là thêm tác giả vào mảng tác phẩm, nhưng như thế sẽ thành ra phân vị trí các thành phần trong khi ta cần giữ cho mối liên hệ giữa tác giả với tác phẩm được bảo toàn.

+ +

Cách tốt hơn là lấy _id của tác giả, rồi dùng find() để tìm trong trường tác giả xuyên suốt tác phẩm.

+ +
Story
+.find({ author : bob._id })
+.exec(function (err, stories) {
+  if (err) return handleError(err);
+  // trả về tất cả các tác phẩm có id của Bob.
+});
+
+
+ +

Đến đây là đã đủ hết mọi thứ bạn cần biết trong bài viết này rồi. Để biết thêm thông tin chi tiết, mời bạn tham khảo Population (tài liệu của Mongoose).

+ +

Một schema/mô hình trên một tập tin

+ +

Dù bạn có thể tạo ra schema và mô hình theo bất cứ kiến trúc nào bạn thích, nhưng chúng tôi vẫn khuyến nghị nên định nghĩa chúng trên mỗi mô đun riêng rẽ (tập tin), rồi xuất mô hình ra ngoài. Làm như thế này này:

+ +
// Tập tin: ./models/somemodel.js
+
+//Nhập Mongoose
+var mongoose = require('mongoose');
+
+//Định nghĩa một schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+    a_string          : String,
+    a_date            : Date,
+});
+
+//Xuất ra lớp mô hình "SomeModel"
+module.exports = mongoose.model('SomeModel', SomeModelSchema );
+ +

Sau đó bạn có thể nhập và sử dụng mô hình ngay tắp lự ở bất cứ đâu. Dưới đây là cách bạn lấy ra mọi phần tử của mô hình.

+ +
//Thê mới mô hình SomeModel thông qua lệnh require
+var SomeModel = require('../models/somemodel')
+
+// Sử dụng đối tượng SomeModel để tìm tất cả bản ghi của SomeModel
+SomeModel.find(callback_function);
+ +

Thiết lập cơ sở dữ liệu MongoDB

+ +

Giờ khi đã hiểu những gì Mongoose có thể làm và cách để ta có thể thiết kế một cơ sở dữ liệu, đến lúc thực hành trên trang web LocalLibrary rồi. Bước đầu tiên trong bài thực hành là tạo mới một cơ sở dữ liệu MongoDb để lưu trữ dữ liệu cho thư viện của chúng ta.

+ +

Trong bài viết này ta sẽ sử dụng cơ sở dữ liệu nền điện toán đám mây của mLab (chọn kiểu "sandbox" để dùng miễn phí). Cơ sở dữ liệu kiểu này không phù hợp dành cho các trang web thật vì nó không có dư thừa dữ liệu, nhưng lại rất hợp dành cho việc phát triển và xây dựng mẫu vật. Và bởi nó dễ dùng cũng như dễ thiết lập, và đừng quên rằng mLab là một trong những bên cung cấp khá nổi tiếng cơ sở dữ liệu cung cấp dưới dạng dịch vụ mà bạn có thể sẽ dùng cho dự án thật (vào thời điểm viết bài này bạn cũng có thể chọn các nhà cung cấp như Compose, ScaleGrid và MongoDB Atlas).

+ +
+

Lưu ý: Nếu bạn muốn thiết lập cơ sở dữ liệu MongoDb cục bộ thì hãy tìm và tải xuống bản phù hợp với hệ thống của mình. Phần còn lại khá là đơn giản, trừ phần URL của cơ sở dữ liệu mà bạn sẽ phải xác định nếu muốn kết nối tới.

+
+ +

Trước hết bạn cần tạo tài khoản mLab (miễn phí, chỉ cần điền mẫu đăng ký là xong). 

+ +

Sau khi đã đăng nhập vào, bạn sẽ được chuyển tới trang chủ:

+ +
    +
  1. Nhấn Create New trong phần MongoDB Deployments.
  2. +
  3. Nó sẽ mở ra màn hình Cloud Provider Selection.
    + MLab - screen for new deployment
    + +
      +
    • Chọn SANDBOX (Free) plan trong phần Plan Type. 
    • +
    • Chọn bất cứ nhà cung cấp nào trong phần Cloud Provider. Mỗi nhà cung cấp khác nhau ở các vùng lãnh thổ địa lý khác nhau (ở ngay dưới phần selected plan type).
    • +
    • Bấm nút Continue.
    • +
    +
  4. +
  5. Màn hình Select Region mở ra. +

    Select new region screen

    + +
      +
    • +

      Chọn vùng lãnh thổ gần bạn nhất rồi nhấn Continue.

      +
    • +
    +
  6. +
  7. +

    Màn hình Final Details mở ra.
    + New deployment database name

    + +
      +
    • +

      Nhập tên cho cơ sở dữ liệu vừa tạo ra như local_library và chọn Continue.

      +
    • +
    +
  8. +
  9. +

    Màn hình Order Confirmation sẽ mở lên.
    + Order confirmation screen

    + +
      +
    • +

      Nhấn Submit Order để tạo mới cơ sở dữ liệu.

      +
    • +
    +
  10. +
  11. +

    Bạn sẽ được điều hướng về trang chủ. Nhấn vào cơ sở dữ liệu vừa thêm mới để xem chi tiết. Như bạn thấy đấy, cơ sở dữ liệu không có bất cứ bộ sưu tập nào (dữ liệu).
    + mLab - Database details screen
    +  
    + URL mà bạn cần ở ngay đầu trang (trong phần khoanh đỏ). Để dùng được nó bạn phải tạo ra người dùng mới.

    +
  12. +
  13. Nhấn vào tab Users và bấm nút Add database user.
  14. +
  15. Điền tên đăng nhập và mật khẩu (hai lần), và nhấn nút Create. Đừng bao giờ chọn Make read only.
    +
  16. +
+ +

Giờ đã có cơ sở dữ liệu rồi, và cả URL (với tên đăng nhập và mật khẩu) đã sẵn sàng để truy xuất. Trông nó sẽ như thế này: mongodb://your_user_namer:your_password@ds119748.mlab.com:19748/local_library.

+ +

Cài đặt Mongoose

+ +

Mở command prompt và chuyển tới thư mục chứa trang web Local Library. Nhập lệnh dưới để cài đặt Mongoose (và đống dependency của nó) và nó sẽ tự động thêm vào package.json của bạn, nếu bạn đã làm như với Mongoose Primer ở trên.

+ +
npm install mongoose --save
+
+ +

Kết nối tới MongoDB

+ +

Mở /app.js (trong project của bạn) và sao chép đống phía dưới để khai báo đối tượng ứng dụng Express (sau dòng var app = express();). Thay thế url của cơ sở dữ liệu ('insert_your_database_url_here') bằng URL của mình (như cái vừa tạo ra bằng mLab).

+ +
//Thiết lập kết nối tới Mongoose
+var mongoose = require('mongoose');
+var mongoDB = 'insert_your_database_url_here';
+mongoose.connect(mongoDB);
+mongoose.Promise = global.Promise;
+var db = mongoose.connection;
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

Như đã nói trong phần Mongoose primer phía trên, đoạn code này tạo ra kết nối mặc định tới cơ sở dữ liệu và ràng buộc sự kiện lỗi (để in lỗi ra console). 

+ +

Định nghĩa Schema cho LocalLibrary

+ +

Ta sẽ tạo ra mô đun cho từng mô hình, như đã đề cập phía trên. Bắt đầu bằng cách thêm mới thư mục trong thư mục gốc (/models) và tạo từng tập tin cho mỗi mô hình:

+ +
/express-locallibrary-tutorial  //the project root
+  /models
+    author.js
+    book.js
+    bookinstance.js
+    genre.js
+
+ +

Mô hình tác giả

+ +

Sao chép đoạn code schema Author code bên dưới và dán vào tập tin ./models/author.js. Scheme định nghĩa rằng một tác giả có kiểu String SchemaTypes cho hai trường họ và tên , bắt buộc và có giới hạn nhiều nhất 100 ký tự, và kiểu Date cho trường ngày sinh và ngày mất.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var AuthorSchema = new Schema(
+  {
+    first_name: {type: String, required: true, max: 100},
+    family_name: {type: String, required: true, max: 100},
+    date_of_birth: {type: Date},
+    date_of_death: {type: Date},
+  }
+);
+
+// Tạo phương thức ảo cho tên đầy đủ
+AuthorSchema
+.virtual('name')
+.get(function () {
+  return this.family_name + ', ' + this.first_name;
+});
+
+// Phương thức ảo cho URL của tác giả
+AuthorSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/author/' + this._id;
+});
+
+//xuất mô hình
+module.exports = mongoose.model('Author', AuthorSchema);
+
+
+ +

Ta vừa khai báo phần ảo cho AuthorSchema với tên là "url" trả về URL tuyệt đối bắt buộc để lấy ra phần tử nhất định của mô hình — ta sẽ dùng thuộc tính này trong mẫu mỗi khi cần lấy ra đường dẫn tới tác giả.

+ +
+

Lưu ý: Khai báo URL bằng hàm ảo trong schema là ý tưởng tốt bởi vì URL sẽ chỉ cần thay đổi tại một nơi.
+ Vào lúc này các URL sẽ không thể hoạt động, ta chưa đặt ra các route nào để dẫn lối cho từng phần tử của mô hình. Ta sẽ làm việc này trong các bài viết sau!

+
+ +

Sau khi đã xong thì ta xuất mô hình ra thôi.

+ +

Mô hình sách

+ +

Sao chép đoạn code schema Book bên dưới và dán nó vào tập tin ./models/book.js. Làm tương tự đối như với tác giả — ta vừa khai báo một schema có nhiều trường String và một phần ảo để lấy URL của các bản ghi sách, sau đó thì xuất nó ra.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookSchema = new Schema(
+  {
+    title: {type: String, required: true},
+    author: {type: Schema.ObjectId, ref: 'Author', required: true},
+    summary: {type: String, required: true},
+    isbn: {type: String, required: true},
+    genre: [{type: Schema.ObjectId, ref: 'Genre'}]
+  }
+);
+
+// Tạo hàm ảo lấy URL của sách
+BookSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/book/' + this._id;
+});
+
+//Xuất mô hình
+module.exports = mongoose.model('Book', BookSchema);
+
+ +

Sự khác biệt chính là ta vừa tạo ra hai mối liên quan đến sách:

+ + + +

Mô hình BookInstance

+ +

Cuối cùng sao chép đoạn code schema BookInstance bên dưới và dán nó vào tập tin ./models/bookinstance.jsBookInstance đại diện cho số bản sách mà ai đó mượn, và bao gồm thông itn về thời điểm sách  về hoặc hạn trả sách dự kiến, "đánh dấu" hoặc lấy chi tiết phiên bản.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookInstanceSchema = new Schema(
+  {
+    book: { type: Schema.ObjectId, ref: 'Book', required: true }, //reference to the associated book
+    imprint: {type: String, required: true},
+    status: {type: String, required: true, enum: ['Available', 'Maintenance', 'Loaned', 'Reserved'], default: 'Maintenance'},
+    due_back: {type: Date, default: Date.now}
+  }
+);
+
+// Lấy ra URL của bookinstance
+BookInstanceSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/bookinstance/' + this._id;
+});
+
+//Xuất mô hình
+module.exports = mongoose.model('BookInstance', BookInstanceSchema);
+ +

Các thuộc tính mới được thêm vào trong này nằm trong phần trường dữ liệu:

+ + + +

Những schema còn lại làm tương tự.

+ +

Mô hình thể loại - thử thách!

+ +

Mở tập tin ./models/genre.js của bạn lên và tạo mới một schema để lưu lại thể loại sách (các kiểu sách như là truyện tiểu thuyết, tư liệu lịch sử...).

+ +

Cách định nghĩa cũng giống như các mô hình ở trên:

+ + + +

Kiểm thử — tạo ra vài bản ghi

+ +

Xong xuôi rồi đó. Giờ ta đã có tất cả mô hình!

+ +

Để có thể kiểm thử mô hình (và để tạo ra vài sách mẫu và một số thứ khác ta sẽ dùng trong bài viết sau) ta sẽ chạy một đoạn kịch bản independent để tạo ra các bản ghi cho từng mô hình:

+ +
    +
  1. Tải về (hoặc tạo mới) tập tin populatedb.js trong thư mục express-locallibrary-tutorial (đồng cấp với package.json). + +
    +

    Lưu ý: Bạn không cần hiểu cách thức populatedb.js hoạt động; nó chỉ thêm dữ liệu mẫu vào trong cơ sở dữ liệu thôi.

    +
    +
  2. +
  3. Nhập lệnh phía dưới vào trong thư mục chứa project để cài đặt mô-đun async để có thể chạy được đoạn kịch bản (ta sẽ bàn về việc này trong bài tiếp theo, ) +
    npm install async --save
    +
  4. +
  5. Chạy đoạn kịch bản bằng node trong command prompt của bạn, truyền vào URL của cơ sở dữ liệu MongoDB (như cái bạn đã thay thế cho insert_your_database_url_here, trong app.js phía trên): +
    node populatedb <your mongodb url>​​​​
    +
  6. +
  7. Đoạn code sẽ chạy thành công và in ra những vật được tạo ra trên màn console.
  8. +
+ +
+

Mẹo: Lên cơ sở dữ liệu của bạn trên mLab. Giờ bạn có thể chui vào bộ sưu tập Books, Authors, Genres và BookInstances, và kiểm tra các tài liệu vừa được tạo.

+
+ +

Tóm lại

+ +

Trong bài viết này ta học một chút về cơ sở dữ liệu và ORMs trên Node/Express, và cách để định nghĩa schema và mô hình của Mongoose. Sau đó ta đã thực hành thiết kế và triển khai các mô hình Book, BookInstance, Author và Genre cho trang web LocalLibrary.

+ +

Sau cùng ta kiểm thử những gì vừa viết ra bằng cách tạo một đống các phần tử (bằng cách sử dụng một đoạn mã kịch bản). Trong bài tiếp theo ta sẽ học cách tạo các trang để trình bày các thứ.

+ +

Đọc thêm

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/vi/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/vi/learn/server-side/express_nodejs/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..3f1fa21d2f --- /dev/null +++ b/files/vi/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -0,0 +1,89 @@ +--- +title: 'Express Tutorial: The Local Library website' +slug: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +translation_of: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +--- +
+

{{LearnSidebar}}

+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}

+
+ +

Đây là bài đầu tiên sẽ giải thích những gì chúng ta sẽ học và giới thiệu tổng quan về dự án thư viên cục bộ mà chúng ta sẽ cải tiến trong suốt khoá học.

+ + + + + + + + + + + + +
Điều kiện tiền quyết:Đọc bài  Express Introduction. Sau đó bạn cũng cẩn phải cài đặt môi trường phát triển Node set up a Node development environment
Mục tiêu:Để giới thiệu ví dụ sẽ được sử dụng trong bài học và giúp người đọc hiểu những chủ đề sẽ được dạy.
+ +

Khái quát

+ +

Chào mứng đến với bộ tài liệu sử dụng Express(Node) để xây dựng một trang web quản lý các chỉ mục trong thư viện.

+ +

Trong loạt bài học này, bạn sẽ được day:

+ + + +

Nếu bạn đã học những chủ đề này rồi và lướt sơ qua các phần khác. Tới cuối loạt bài học này bạn sẽ đủ hiểu biết để phát triển một ứng dụng đơn giản với Express.

+ +

LocalLibrary website

+ +

LocalLibrary là tên của website mà bạn sẽ tạo ra và cải tiến trong loạt các bài học này. Như bạn mong đợi, mục tiêu của trang web là cung cấp một danh mục trực tuyến cho một thư viện cục bộ nhỏ, nơi mà người dùng có thể truy cập những quyển sách có sẵn và quản lý tài khoản của họ.

+ +

Ví dụ này được lựa chọn rất cẩn thận bởi vì nó có thể được điều chỉnh để chỉ hiển thị những chức năng vừa phải để có thể ứng dụng hầu hết các chức năng của Express. Quan trọng hơn nữa, nó giúp chúng tôi vẽ ra con đường để hướng dẫn các chức năng cần thiệt trong việc phát triển bất kỳ website nào :

+ + + +

Tuy đây là một ví dụ có tính mở rộng cao, nhưng nó được gọi là "LocalLibrary" bởi vì chúng tôi hy vọng chỉ để thể hiện những thông tin tối thiểu để giúp bạn bắt đầu với Express một cách nhanh chóng. Cho nên chúng ta sẽ lưu thông tin về sách, bản sao sách, tác giả và các thông tin mấu chốt khác, mà chúng ta không lưu thông tin về những phần khác thư viện như việc cho mượn hay cơ sở hạ tầng để hỗ trợ đặt trang web cho thư viện hay những chức năng cho một "thư viện lớn".

+ +

Khi gặp khó khăn, thì tham khảo ở đâu? 

+ +

Trong suốt tài liệu chúng tôi sẽ cung cấp những đoạn mã nguồn mà bạn có thể tham khảo ở mỗi phần, và có nhiều mã nguồn khác mà chúng tôi hi vọng bạn sẽ mở rộng nó.

+ +

Nếu bạn bí quá thì có thể tham khảo toàn bộ mã nguồn của website trên Github.

+ +
+

Chú ý:  Những phiên bản của node, Express và những modules khác mà tài liệu này sử dụng được liệt kê ở trong package.json.

+
+ +

Tổng Kết

+ +

Bây giờ bạn đã biết về dự án LocalLibrary, giờ thì bắt đầu tạo cấu trúc dự án nào.

+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/vi/learn/server-side/first_steps/index.html b/files/vi/learn/server-side/first_steps/index.html new file mode 100644 index 0000000000..95ddf775ab --- /dev/null +++ b/files/vi/learn/server-side/first_steps/index.html @@ -0,0 +1,46 @@ +--- +title: Các bước đầu tiên để lập trình trang web phía máy chủ +slug: Learn/Server-side/First_steps +tags: + - Giới thiệu + - Hướng dẫn + - Học + - Lập trình máy chủ + - Ngôn ngữ lập trình + - Người Mới Bắt Đầu +translation_of: Learn/Server-side/First_steps +--- +
{{LearnSidebar}}
+ +

Trong mô-đun này chúng ta tìm cầu trả lời về một vài câu hỏi chức năng về lập trình phía máy chủ — "Nó là gì?", "Nó khác như nào so với lập trình phía máy khách ?", và "Tại sao nó lại hữu ích?". Tiếp theo chúng ta tìm hiểu tổng quan về một số framework (Một nền tảng bao gồm các tệp/thư mục tạo sẵn được quy chuẩn khi sử dụng nó để lập trình khi tạo một dự án mới) phổ biến để tạo web phía máy chủ, cùng với hướng dẫn phù hợp nhất để lựa chọn framework phù hợp để tạo trang web đầu tiên của bạn. Cuối cùng chúng ta tìm hiểu bài viết cấp cao về bảo mật máy chủ web.

+ +

Kiến thức yêu cầu 

+ +

Trước khi bắt đầu mô-dun này, bạn không cần phải có bất kỳ hiểu biết nào về lập trình phía máy chủ, hoặc bất kỳ ngôn ngữ lập trình nào khác. 

+ +

Tuy nhiên, bạn cần hiểu về cách web làm việc. Chúng tôi đề xuất bạn nên đọc các chủ đề này trước khi bắt đầu:

+ + + +

Với các hiểu biết cơ bản, bạn sẽ sẵn sàng để làm việc theo cách của mình thông qua các mô-dun trong phần này. 

+ +

Hướng dẫn

+ +
+
Giới thiệu về phía máy chủ 
+
Chào mừng bạn đến với khóa học lập trình phía máy chủ của MDN cho người mới bắt đầu! Trong bài viết đầu tiên này, chúng tôi xem xét lập trình phía máy chủ từ cấp độ cao, trả lời các câu hỏi như "Nó là gì?", "Nó khác với lập trình phía máy khách như thế nào?" Và "Tại sao nó lại hữu ích như vậy?" . Sau khi đọc bài viết này, bạn sẽ hiểu sức mạnh bổ sung có sẵn cho các trang web thông qua mã hóa phía máy chủ.
+
Tổng quan về Khách-Chủ 
+
Bây giờ bạn đã biết mục đích và lợi ích tiềm năng của lập trình phía máy chủ, chúng ta sẽ kiểm tra chi tiết điều gì xảy ra khi máy chủ nhận được "yêu cầu động" từ trình duyệt. Vì mã phía máy chủ của hầu hết các trang web xử lý các yêu cầu và phản hồi theo cách tương tự, điều này sẽ giúp bạn hiểu những gì bạn cần làm khi viết mã của riêng mình. 
+
Các framework phía máy chủ
+
Bài viết cuối cùng cho bạn thấy một ứng dụng web phía máy chủ cần làm gì để đáp ứng các yêu cầu từ trình duyệt web. Bây giờ chúng tôi chỉ ra cách các khung web có thể đơn giản hóa các tác vụ này và giúp bạn chọn khung phù hợp cho ứng dụng web phía máy chủ đầu tiên của bạn.
+
Bảo mật trang web 
+
Bảo mật trang web đòi hỏi sự cảnh giác trong tất cả các khía cạnh của thiết kế và sử dụng. Bài viết giới thiệu này sẽ không làm bạn thành một chuyên gia bảo mật trang web, nhưng nó sẽ giúp bạn hiểu các bước quan trọng đầu tiên bạn có thể thực hiện để bảo vệ ứng dụng web của mình trước các mối đe dọa phổ biến nhất.
+
+ +

Đánh giá

+ +

Mô-đun "tổng quan" này không có bất kỳ đánh giá nào vì chúng tôi chưa hiển thị cho bạn bất kỳ mã nào. Chúng tôi hy vọng rằng tại thời điểm này, bạn hiểu rõ về loại chức năng nào bạn có thể cung cấp bằng lập trình phía máy chủ và bạn đã đưa ra quyết định về khung web phía máy chủ nào bạn sẽ sử dụng để tạo trang web đầu tiên của mình.

diff --git a/files/vi/learn/server-side/first_steps/introduction/index.html b/files/vi/learn/server-side/first_steps/introduction/index.html new file mode 100644 index 0000000000..9594c42833 --- /dev/null +++ b/files/vi/learn/server-side/first_steps/introduction/index.html @@ -0,0 +1,228 @@ +--- +title: Introduction to the server side +slug: Learn/Server-side/First_steps/Introduction +translation_of: Learn/Server-side/First_steps/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}
+ +

Chào mừng bạn đến với khóa học lập trình phía máy chủ của người mới bắt đầu MDN! Trong bài viết đầu tiên này, chúng tôi xem xét lập trình phía máy chủ từ cấp độ cao, trả lời các câu hỏi như "nó là gì?", "Nó khác với lập trình phía máy khách như thế nào?" Và "tại sao nó lại hữu ích như vậy?" . Sau khi đọc bài viết này, bạn sẽ hiểu sức mạnh bổ sung có sẵn cho các trang web thông qua mã hóa phía máy chủ.

+ + + + + + + + + + + + +
Điều kiện:Kiến thức cơ bản về máy tính. Một sự hiểu biết cơ bản về những gì là một máy chủ web.
Mục tiêu:Để làm quen với lập trình phía máy chủ là gì, nó có thể làm gì và nó khác với lập trình phía máy khách như thế nào.
+ +

Hầu hết các trang web quy mô lớn sử dụng mã phía máy chủ để hiển thị động các dữ liệu khác nhau khi cần, các dữ liệu thường rút ra khỏi cơ sở dữ liệu được lưu trữ trên máy chủ và được gửi đến máy khách để được hiển thị thông qua một số mã (ví dụ: HTML và JavaScript).

+ +

Có lẽ lợi ích đáng kể nhất của mã phía máy chủ là nó cho phép bạn điều chỉnh nội dung trang web cho từng người dùng. Các trang web động có thể làm nổi bật nội dung phù hợp hơn dựa trên sở thích và thói quen của người dùng. Nó cũng có thể làm cho các trang web dễ sử dụng hơn bằng cách lưu trữ thông tin và sở thích cá nhân - ví dụ: sử dụng lại chi tiết thẻ tín dụng được lưu trữ để hợp lý hóa các khoản thanh toán tiếp theo.

+ +

Nó thậm chí có thể cho phép tương tác với người dùng của trang web, gửi thông báo và cập nhật qua email hoặc qua các kênh khác. Tất cả các khả năng này cho phép tham gia sâu hơn nhiều với người dùng.

+ +

Trong thế giới phát triển web hiện đại, việc tìm hiểu về phát triển phía máy chủ rất được khuyến khích.

+ +

Lập trình trang web phía máy chủ là gì?

+ +

Trình duyệt web giao tiếp với máy chủ web bằng cách sử dụng HyperText Transfer Protocol ({{glossary("HTTP")}}). Khi bạn nhấp vào một liên kết trên một trang web, gửi biểu mẫu hoặc chạy tìm kiếm, một yêu cầu HTTP được gửi từ trình duyệt của bạn đến máy chủ mục tiêu.

+ +

Yêu cầu bao gồm một URL xác định tài nguyên bị ảnh hưởng, một phương thức xác định hành động được yêu cầu (ví dụ để lấy, xóa hoặc đăng tài nguyên) và có thể bao gồm thông tin bổ sung được mã hóa trong các tham số URL (các cặp giá trị trường được gửi qua truy vấn chuỗi), dưới dạng dữ liệu POST (dữ liệu được gửi bởi phương thức HTTP POST ), hoặc trong các {{glossary("Cookie", "cookies")}} được liên kết.

+ +

Các máy chủ web chờ tin nhắn yêu cầu của khách hàng, xử lý chúng khi chúng đến và trả lời trình duyệt web bằng tin nhắn phản hồi HTTP. Phản hồi chứa một dòng trạng thái cho biết liệu yêu cầu có thành công hay không (ví dụ:  "HTTP/1.1 200 OK" for success). 

+ +

Phần chính của phản hồi thành công đối với yêu cầu sẽ chứa tài nguyên được yêu cầu (ví dụ: trang HTML mới hoặc hình ảnh, v.v.), sau đó có thể được trình duyệt web hiển thị.

+ +

Trang web tĩnh

+ +

Sơ đồ bên dưới hiển thị kiến trúc máy chủ web cơ bản cho một trang tĩnh (một trang tĩnh là một trang trả về cùng một nội dung được mã hóa cứng từ máy chủ bất cứ khi nào một tài nguyên cụ thể được yêu cầu). Khi người dùng muốn điều hướng đến một trang, trình duyệt sẽ gửi yêu cầu "GET" HTTP chỉ định URL của nó.

+ +

Máy chủ lấy tài liệu được yêu cầu từ hệ thống tệp của nó và trả về phản hồi HTTP có chứa tài liệu và trạng thái thành công (thường là 200 OK). Nếu một số lý do không thể truy xuất tệp, một trạng thái lỗi được trả về (xem phản hồi lỗi máy kháchphản hồi lỗi máy chủ).

+ +

A simplified diagram of a static web server.

+ +

Trang web động

+ +

Trang web động là một trong đó một số nội dung phản hồi được tạo động, chỉ khi cần. Trên trang web động, các trang HTML thường được tạo bằng cách chèn dữ liệu từ cơ sở dữ liệu vào trình giữ chỗ trong các mẫu HTML (đây là cách lưu trữ lượng lớn nội dung hiệu quả hơn nhiều so với sử dụng trang web tĩnh).

+ +

Trang web động có thể trả về dữ liệu khác nhau cho một URL dựa trên thông tin được cung cấp bởi người dùng hoặc tùy chọn được lưu trữ và có thể thực hiện các hoạt động khác như một phần của việc trả lại phản hồi (ví dụ: gửi thông báo).

+ +

Hầu hết các mã để hỗ trợ một trang web động phải chạy trên máy chủ. Tạo mã này được gọi là "lập trình phía máy chủ" (hoặc đôi khi là "kịch bản phía sau").

+ +

Sơ đồ dưới đây cho thấy một kiến trúc đơn giản cho một trang web động. Như trong sơ đồ trước, các trình duyệt gửi yêu cầu HTTP đến máy chủ, sau đó máy chủ xử lý các yêu cầu và trả về các phản hồi HTTP thích hợp.

+ +

Các yêu cầu đối với tài nguyên tĩnh được xử lý theo cách tương tự như đối với các trang web tĩnh (tài nguyên tĩnh là bất kỳ tệp nào không thay đổi về cách thức: CSS, JavaScript, Hình ảnh, tệp PDF được tạo trước, v.v.).

+ +

A simplified diagram of a web server that uses server-side programming to get information from a database and construct HTML from templates. This is the same diagram as is in the Client-Server overview.

+ +

Yêu cầu tài nguyên động thay vào đó được chuyển tiếp (2) sang mã phía máy chủ (được hiển thị trong sơ đồ dưới dạng Ứng dụng web). Đối với "yêu cầu động", máy chủ diễn giải yêu cầu, đọc thông tin bắt buộc từ cơ sở dữ liệu (3), kết hợp dữ liệu được truy xuất với các mẫu HTML (4) và gửi lại phản hồi có chứa HTML được tạo (5,6). 

+ +
+

Các chương trình phía máy chủ và phía máy khách có giống nhau không?

+
+ +

Bây giờ chúng ta hãy chú ý đến mã liên quan đến lập trình phía máy chủ và phía máy khách. Trong mỗi trường hợp, mã là khác nhau đáng kể:

+ + + +

Mã chạy trong trình duyệt được gọi là mã phía máy khách và chủ yếu liên quan đến việc cải thiện giao diện và hành vi của một trang web được hiển thị. Điều này bao gồm lựa chọn và tạo kiểu các thành phần UI, tạo bố cục, điều hướng, xác thực mẫu, v.v ... Ngược lại, lập trình trang web phía máy chủ chủ yếu liên quan đến việc chọn nội dung nào được trả về trình duyệt để đáp ứng yêu cầu. Mã phía máy chủ xử lý các tác vụ như xác thực dữ liệu và yêu cầu đã gửi, sử dụng cơ sở dữ liệu để lưu trữ và truy xuất dữ liệu và gửi dữ liệu chính xác đến máy khách theo yêu cầu.

+ +

Mã phía máy khách được viết bằng HTML, CSSJavaScript - nó được chạy bên trong trình duyệt web và có ít hoặc không có quyền truy cập vào hệ điều hành bên dưới (bao gồm quyền truy cập hạn chế vào hệ thống tệp).

+ +

Các nhà phát triển web không thể kiểm soát trình duyệt mà mọi người dùng có thể đang sử dụng để xem trang web - trình duyệt cung cấp mức độ tương thích không nhất quán với các tính năng mã phía máy khách và một phần thách thức của lập trình phía máy khách là xử lý các khác biệt trong hỗ trợ trình duyệt một cách duyên dáng.

+ +

Mã phía máy chủ có thể được viết bằng bất kỳ số ngôn ngữ lập trình nào - ví dụ về các ngôn ngữ web phía máy chủ phổ biến bao gồm PHP, Python, Ruby, C # và NodeJS (JavaScript). Mã phía máy chủ có toàn quyền truy cập vào hệ điều hành máy chủ và nhà phát triển có thể chọn ngôn ngữ lập trình (và phiên bản cụ thể) mà họ muốn sử dụng.

+ +

Các nhà phát triển thường viết mã của họ bằng cách sử dụng các khung web. Các khung web là tập hợp các hàm, đối tượng, quy tắc và các cấu trúc mã khác được thiết kế để giải quyết các vấn đề phổ biến, tăng tốc độ phát triển và đơn giản hóa các loại nhiệm vụ khác nhau phải đối mặt trong một miền cụ thể.

+ +

Một lần nữa, trong khi cả mã phía máy khách và máy chủ đều sử dụng các khung, các miền rất khác nhau và do đó là các khung. Các khung web phía máy khách đơn giản hóa các tác vụ bố trí và trình bày trong khi các khung web phía máy chủ cung cấp rất nhiều chức năng máy chủ web phổ biến mà bạn có thể phải tự thực hiện (ví dụ: hỗ trợ phiên, hỗ trợ người dùng và xác thực, truy cập cơ sở dữ liệu dễ dàng, thư viện templating, vv).

+ +
+

Note: Client-side frameworks thường được sử dụng để giúp tăng tốc độ phát triển mã phía máy khách, nhưng bạn cũng có thể chọn viết tất cả mã bằng tay; thực tế, viết mã bằng tay có thể nhanh hơn và hiệu quả hơn nếu bạn chỉ cần một giao diện người dùng trang web nhỏ, đơn giản.

+ +


+ Ngược lại, bạn gần như sẽ không bao giờ xem xét việc viết thành phần phía máy chủ của ứng dụng web mà không có framework — thực hiện một tính năng quan trọng như máy chủ HTTP thực sự khó thực hiện từ đầu khi nói Python, nhưng các web frameworks như Django cung cấp một của hộp, cùng với các công cụ rất hữu ích khác.

+
+ +
+

Bạn có thể làm gì ở phía máy chủ?

+ +

Lập trình phía máy chủ rất hữu ích vì nó cho phép chúng tôi cung cấp hiệu quả thông tin phù hợp cho từng người dùng và từ đó tạo ra trải nghiệm người dùng tốt hơn nhiều.

+
+ +

Các công ty như Amazon sử dụng lập trình phía máy chủ để xây dựng kết quả tìm kiếm cho sản phẩm, đưa ra đề xuất sản phẩm được nhắm mục tiêu dựa trên sở thích của khách hàng và thói quen mua trước đó, đơn giản hóa việc mua hàng, v.v.

+ +

Các ngân hàng sử dụng lập trình phía máy chủ để lưu trữ thông tin tài khoản và chỉ cho phép người dùng được ủy quyền xem và thực hiện giao dịch. Các dịch vụ khác như Facebook, Twitter, Instagram và Wikipedia sử dụng lập trình phía máy chủ để làm nổi bật, chia sẻ và kiểm soát quyền truy cập vào nội dung thú vị.

+ +

Một số sử dụng và lợi ích chung của lập trình phía máy chủ được liệt kê bên dưới. Bạn sẽ lưu ý rằng có một số chồng chéo!

+ +

Lưu trữ và cung cấp thông tin hiệu quả

+ +

Hãy tưởng tượng có bao nhiêu sản phẩm có sẵn trên Amazon và tưởng tượng có bao nhiêu bài viết đã được viết trên Facebook? Tạo một trang tĩnh riêng cho từng sản phẩm hoặc bài đăng sẽ hoàn toàn không thực tế.

+ +

Thay vào đó, lập trình phía máy chủ cho phép chúng tôi lưu trữ thông tin trong cơ sở dữ liệu và tự động xây dựng và trả về HTML và các loại tệp khác (ví dụ: PDF, hình ảnh, v.v.). Cũng có thể chỉ cần trả lại dữ liệu ({{glossary("JSON")}}, {{glossary("XML")}}, v.v) để hiển thị bằng các khung web phía máy khách thích hợp (điều này giúp giảm gánh nặng xử lý trên máy chủ và lượng dữ liệu cần gửi).

+ +

Máy chủ không giới hạn gửi thông tin từ cơ sở dữ liệu và có thể trả về kết quả của các công cụ phần mềm hoặc dữ liệu từ các dịch vụ truyền thông. Nội dung thậm chí có thể được nhắm mục tiêu cho loại thiết bị khách đang nhận nó.

+ +

Vì thông tin có trong cơ sở dữ liệu, nên nó cũng có thể dễ dàng chia sẻ và cập nhật hơn với các hệ thống kinh doanh khác (ví dụ: khi sản phẩm được bán trực tuyến hoặc trong cửa hàng, cửa hàng có thể cập nhật cơ sở dữ liệu về hàng tồn kho).

+ +
+

Note: Trí tưởng tượng của bạn không nhất thiết phải làm việc chăm chỉ để xem lợi ích của mã server-side cho việc lưu trữ và cung cấp thông tin hiệu quả:

+ +
    +
  1. Truy cập Amazon hoặc một số trang web thương mại điện tử khác.
  2. +
  3. Tìm kiếm một số từ khóa và lưu ý cách thức cấu trúc trang không thay đổi, mặc dù kết quả thực hiện.
  4. +
  5. Mở hai hoặc ba sản phẩm khác nhau. Lưu ý một lần nữa cách chúng có cấu trúc và bố cục chung, nhưng nội dung cho các sản phẩm khác nhau đã được lấy từ cơ sở dữ liệu.
  6. +
+ +

Đối với cụm từ tìm kiếm chung (giả sử "cá" ), bạn có thể thấy hàng triệu giá trị được trả về theo nghĩa đen. Sử dụng cơ sở dữ liệu cho phép những thứ này được lưu trữ và chia sẻ hiệu quả, và nó cho phép việc trình bày thông tin được kiểm soát chỉ ở một nơi.

+
+ +

Tùy chỉnh trải nghiệm người dùng

+ +

Máy chủ có thể lưu trữ và sử dụng thông tin về khách hàng để cung cấp trải nghiệm người dùng thuận tiện và phù hợp. Ví dụ: nhiều trang web lưu trữ thẻ tín dụng để các chi tiết không phải nhập lại. Các trang web như Google Maps có thể sử dụng các vị trí đã lưu hoặc hiện tại để cung cấp thông tin định tuyến và lịch sử tìm kiếm hoặc du lịch để làm nổi bật các doanh nghiệp địa phương trong kết quả tìm kiếm.

+ +

Một phân tích sâu hơn về thói quen người dùng có thể được sử dụng để dự đoán sở thích của họ và tùy chỉnh thêm các phản hồi và thông báo, ví dụ như cung cấp danh sách các địa điểm phổ biến đã truy cập trước đây hoặc bạn có thể muốn xem trên bản đồ.

+ +
+

Note: Google Maps lưu lịch sử tìm kiếm và truy cập của bạn. Các địa điểm thường xuyên truy cập hoặc tìm kiếm thường được tô sáng hơn các địa điểm khác.

+ +

Kết quả tìm kiếm của Google được tối ưu hóa dựa trên các tìm kiếm trước đó.

+ +
    +
  1.  Chuyển đến tìm kiếm Google.
  2. +
  3.  Tìm kiếm "bóng đá".
  4. +
  5. Bây giờ hãy thử gõ "yêu thích" vào hộp tìm kiếm và quan sát các dự đoán tìm kiếm tự động hoàn tất.
  6. +
+ +

Sự trùng hợp? Không có gì!

+
+ +

Kiểm soát truy cập nội dung

+ +

Lập trình phía máy chủ cho phép các trang web hạn chế quyền truy cập đối với người dùng được ủy quyền và chỉ cung cấp thông tin mà người dùng được phép xem.

+ +

Các ví dụ trong thế giới thực bao gồm:

+ + + +
+

Note: Xem xét các ví dụ thực tế khác, nơi quyền truy cập vào nội dung được kiểm soát. Ví dụ: bạn có thể thấy gì nếu bạn truy cập trang web trực tuyến cho ngân hàng của mình? Đăng nhập vào tài khoản của bạn - bạn có thể xem và sửa đổi thông tin bổ sung nào? Thông tin nào bạn có thể thấy rằng chỉ có ngân hàng mới có thể thay đổi?

+
+ +

Lưu trữ thông tin phiên / trạng thái

+ +

Lập trình phía máy chủ cho phép các nhà phát triển sử dụng các phiên - về cơ bản, một cơ chế cho phép máy chủ lưu trữ thông tin về người dùng hiện tại của trang web và gửi các phản hồi khác nhau dựa trên thông tin đó.

+ +

Ví dụ, điều này cho phép một trang web biết rằng người dùng đã đăng nhập trước đó và hiển thị các liên kết đến email hoặc lịch sử đặt hàng của họ hoặc có thể lưu trạng thái của một trò chơi đơn giản để người dùng có thể truy cập lại trang web và tiếp tục họ đã bỏ nó

+ +
+

Note: Truy cập trang web báo có mô hình đăng ký và mở một loạt các tab (ví dụ: The Age). Tiếp tục truy cập trang web trong một vài giờ / ngày. Cuối cùng, bạn sẽ bắt đầu được chuyển hướng đến các trang giải thích cách đăng ký và bạn sẽ không thể truy cập các bài viết. Thông tin này là một ví dụ về thông tin phiên được lưu trữ trong cookie.

+
+ +

Thông báo và liên lạc

+ +

Máy chủ có thể gửi thông báo chung hoặc cụ thể cho người dùng thông qua trang web hoặc qua email, SMS, tin nhắn tức thời, cuộc trò chuyện video hoặc các dịch vụ liên lạc khác.

+ +

Một vài ví dụ bao gồm:

+ + + +
+

Note: Loại thông báo phổ biến nhất là "xác nhận đăng ký". Chọn hầu hết mọi trang web lớn mà bạn quan tâm (Google, Amazon, Instagram, v.v.) và tạo một tài khoản mới bằng địa chỉ email của bạn. Bạn sẽ sớm nhận được một email xác nhận đăng ký của bạn hoặc yêu cầu xác nhận để kích hoạt tài khoản của bạn.

+
+ +

Phân tích dữ liệu

+ +

Một trang web có thể thu thập rất nhiều dữ liệu về người dùng: những gì họ tìm kiếm, những gì họ mua, những gì họ giới thiệu, thời gian họ ở lại trên mỗi trang. Lập trình phía máy chủ có thể được sử dụng để tinh chỉnh các phản hồi dựa trên phân tích dữ liệu này.

+ +

Ví dụ: Amazon và Google đều quảng cáo sản phẩm dựa trên các tìm kiếm trước đó (và mua hàng).

+ +
+

Note: Nếu bạn là người dùng Facebook, hãy truy cập nguồn cấp dữ liệu chính của bạn và xem luồng bài đăng. Lưu ý cách một số bài đăng không theo thứ tự số - cụ thể, các bài đăng có nhiều lượt "thích" thường cao hơn trong danh sách so với các bài đăng gần đây.

+ +

Ngoài ra, hãy nhìn vào loại quảng cáo bạn đang được hiển thị - bạn có thể thấy quảng cáo cho những thứ bạn đã xem trên các trang web khác. Thuật toán của Facebook để làm nổi bật nội dung và quảng cáo có thể là một bí ẩn, nhưng rõ ràng là nó phụ thuộc vào sở thích và thói quen xem của bạn!

+
+ +

Tóm lược

+ +

Xin chúc mừng, bạn đã đến cuối bài viết đầu tiên về lập trình phía máy chủ. 

+ +

Bây giờ bạn đã biết rằng mã phía máy chủ được chạy trên máy chủ web và vai trò chính của nó là kiểm soát thông tin nào được gửi đến người dùng (trong khi mã phía máy khách chủ yếu xử lý cấu trúc và trình bày dữ liệu đó cho người dùng) 

+ +

Bạn cũng nên hiểu rằng nó hữu ích vì nó cho phép chúng tôi tạo các trang web cung cấp thông tin phù hợp cho người dùng cá nhân và có ý tưởng tốt về một số điều bạn có thể làm khi bạn là lập trình viên phía máy chủ.

+ +

Cuối cùng, bạn nên hiểu rằng mã phía máy chủ có thể được viết bằng một số ngôn ngữ lập trình và bạn nên sử dụng web framework để làm cho toàn bộ quá trình dễ dàng hơn.

+ +

Trong một bài viết trong tương lai, chúng tôi sẽ giúp bạn chọn web framework tốt nhất cho trang web đầu tiên của bạn. Ở đây chúng tôi sẽ đưa bạn qua các tương tác máy khách-máy chủ chính chỉ chi tiết hơn một chút.

+ +

{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}

+ +

In this module

+ + diff --git a/files/vi/learn/server-side/index.html b/files/vi/learn/server-side/index.html new file mode 100644 index 0000000000..e2c651cc55 --- /dev/null +++ b/files/vi/learn/server-side/index.html @@ -0,0 +1,59 @@ +--- +title: Lập trình website khía cạnh server +slug: Learn/Server-side +tags: + - Beginner + - CodingScripting + - Intro + - Landing + - Learn + - NeedsTranslation + - Server + - Server-side programming + - Topic + - TopicStub +translation_of: Learn/Server-side +--- +
{{LearnSidebar}}
+ +

Chủ đề Web động - Lập trình phía máy chủ là một loạt các bài viết hướng dẫn cách tạo ra các trang web động; là các trang web sẽ cung cấp thông tin tùy chỉnh dựa trên một yêu cầu HTTP. Các bài viết sẽ cung cấp một sự giới thiệu chung cho lập trình phía máy chủ, đi kèm với hướng dẫn cụ thể cho người mới bắt đầu trên các framework như Django (Python) và Express (Node.js/Javascript) để tạo nên các ứng dụng cơ bản.

+ +

Các trang web phổ biến nhất sử dụng một số kỹ thuật về phía máy chủ để hiển thị dữ liệu động khác nhau khi được yêu cầu. Ví dụ, hình dung rằng có bao nhiêu sản phẩm bày bán trên Amazon, và hình dung rằng có bao nhiêu bài đăng được viết trên Facebook? Việc hiển thị tất cả những nội dung đó trên các trang tĩnh là hoàn toàn không hiệu quả, do đó thay vì các trang hiển thị tĩnh (xây dựng dựa trên HTML, CSS và Javascript), thì tự động cập nhật dữ liệu được hiển thị bên trong các trang đó khi cần, ví dụ: khi bạn muốn xem một sản phẩm khác trên Amazon. 

+ +

Trong thế giới phát trển web hiện đại, việc học về phát triển phía máy chủ rất được khuyến khích.

+ +

Chặng đường học tập

+ +

Bắt đầu với lập trình phía máy chủ thường dễ hơn so với phát triển phía máy khách, vì các trang web động có xu hướng thực hiện rất nhiều hoạt động tương tự nhau( lấy dữ liệu từ cơ sở dữ liệu và hiển thị nó trong một trang, xác thực dữ liệu do người dùng nhập và lưu nó trong cơ sở dữ liệu, kiểm tra quyền người dùng và ghi nhật ký người dùng, v.v.) và được xây dựng bằng cách sử dụng web framework làm cho các thao tác trên máy chủ web trở nên dễ dàng hơn.

+ +

Một kiến ​​thức cơ bản về các khái niệm lập trình (hoặc của một ngôn ngữ lập trình cụ thể) là hữu ích, nhưng không cần thiết. Tương tự như vậy, chuyên môn về lập trình phía máy khách là không cần thiết, nhưng kiến ​​thức cơ bản sẽ giúp bạn làm việc tốt hơn với các nhà phát triển tạo trang web phía máy khách của bạn.

+ +

Bạn sẽ cần phải hiểu "web làm việc thế nào". Chúng tôi giới thiệu bạn một số chủ đề cơ bản:

+ + + +

Với sự hiểu biết cơ bản, bạn sẽ sẵn sàng để qua phần Modules trong bài viết này. 

+ +

Modules

+ +

Chủ đề này chứa một số module. Bạn nên bắt đầu với module đầu tiên, sau đó đến 1 trong 2 module sau, đây là 2 ngôn ngữ server side rất phổ biến sẽ cho bạn thấy cách nó hoạt động

+ +
+
Server-side website programming first steps
+
This module provides server-technology-agnostic information about server-side website programming, including answers to fundamental questions about server-side programming — "what it is", "how it differs from client-side programming", and "why it is so useful" — and an overview of some of the more popular server-side web frameworks and guidance on how to select the most suitable for your site. Lastly we provide an introductory section on web server security.
+
Django Web Framework (Python)
+
Django is an extremely popular and fully featured server-side web framework, written in Python. The module explains why Django is such a good web server framework, how to set up a development environment and how to perform common tasks with it.
+
Express Web Framework (Node.js/JavaScript)
+
Express is a popular web framework, written in JavaScript and hosted within the node.js runtime environment. The module explains some of the key benefits of this framework, how to set up your development environment and how to perform common web development and deployment tasks.
+
+ +

Xem thêm

+ +
+
Node server without framework
+
This article provides a simple static file server built with pure Node.js, for those of you not wanting to use a framework.
+
-- cgit v1.2.3-54-g00ecf