GraphQL - Hướng dẫn nhanh

GraphQL là một công nghệ phía máy chủ mã nguồn mở được Facebook phát triển để tối ưu hóa các lệnh gọi API RESTful. Nó là một công cụ thực thi và một ngôn ngữ truy vấn dữ liệu. Trong chương này, chúng ta thảo luận về những lợi thế của việc sử dụng GraphQL.

Tại sao nên dùng GraphQL

Các API RESTful tuân theo cách tiếp cận định hướng tài nguyên rõ ràng và có cấu trúc tốt. Tuy nhiên, khi dữ liệu trở nên phức tạp hơn, các tuyến đường sẽ dài hơn. Đôi khi không thể tìm nạp dữ liệu với một yêu cầu duy nhất. Đây là lúc GraphQL có ích. GraphQL cấu trúc dữ liệu dưới dạng biểu đồ với cú pháp truy vấn mạnh mẽ để duyệt, truy xuất và sửa đổi dữ liệu.

Sau đây là những ưu điểm của việc sử dụng Ngôn ngữ truy vấn GraphQL:

Yêu cầu những gì bạn muốn - và nhận được nó

Gửi một truy vấn GraphQL tới API của bạn và nhận chính xác những gì bạn cần. Các truy vấn GraphQL luôn trả về kết quả có thể dự đoán được. Các ứng dụng sử dụng GraphQL rất nhanh và ổn định. Không giống như các dịch vụ Restful, các ứng dụng này có thể hạn chế dữ liệu cần được tìm nạp từ máy chủ.

Ví dụ sau sẽ giúp bạn hiểu rõ hơn về điều này -

Chúng ta hãy xem xét một đối tượng doanh nghiệp là Sinh viên với các thuộc tính id, firstName, lastNamecollegeName . Giả sử một ứng dụng di động chỉ cần tìm nạp FirstNameid . Nếu chúng ta thiết kế một điểm cuối REST như / api / v1 / students , nó sẽ kết thúc việc tìm nạp dữ liệu cho tất cả các trường cho một đối tượng student . Điều này có nghĩa là, dữ liệu được dịch vụ RESTful tìm nạp quá mức. Vấn đề này có thể được giải quyết bằng cách sử dụng GraphQL.

Hãy xem xét truy vấn GraphQL được đưa ra bên dưới:

{
   students {
      id
      firstName
   }
}

Điều này sẽ chỉ trả về giá trị cho các trường id và tên. Truy vấn sẽ không tìm nạp giá trị cho các thuộc tính khác của đối tượng sinh viên. Phản hồi của truy vấn được minh họa ở trên như được hiển thị bên dưới -

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim"
         },
         {
            "id": "S1002",
            "firstName": "Kannan"
         }
      ]
   }
}

Nhận nhiều tài nguyên trong một yêu cầu duy nhất

Các truy vấn GraphQL giúp truy xuất suôn sẻ các đối tượng kinh doanh được liên kết, trong khi các API REST điển hình yêu cầu tải từ nhiều URL. Các API GraphQL tìm nạp tất cả dữ liệu mà ứng dụng của bạn cần trong một yêu cầu duy nhất. Các ứng dụng sử dụng GraphQL có thể nhanh chóng ngay cả trên các kết nối mạng di động chậm.

Chúng ta hãy xem xét một đối tượng kinh doanh nữa, College có các thuộc tính: tên và địa điểm. Các sinh viên đối tượng kinh doanh có mối quan hệ gắn với đối tượng College. Nếu chúng tôi sử dụng API REST để tìm nạp thông tin chi tiết của sinh viên và trường đại học của họ, chúng tôi sẽ đưa ra hai yêu cầu tới máy chủ như / api / v1 / Students/ api / v1 / college . Điều này sẽ dẫn đến việc tìm nạp dữ liệu với mỗi yêu cầu. Vì vậy các ứng dụng di động buộc phải thực hiện nhiều cuộc gọi đến máy chủ để có được dữ liệu mong muốn.

Tuy nhiên, ứng dụng di động có thể tìm nạp thông tin chi tiết cho cả đối tượng Sinh viên và Cao đẳng trong một yêu cầu duy nhất bằng cách sử dụng GraphQL.

Sau đây là truy vấn GraphQL để tìm nạp dữ liệu:

{
   students{
      id
      firstName
      lastName
      college{
         name
         location
      }
   }
}

Đầu ra của truy vấn trên chứa chính xác những trường mà chúng tôi đã yêu cầu như được hiển thị bên dưới:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim",
            "lastName": "Mohammad",
            "college": {
               "name": "CUSAT",
               "location": "Kerala"
            }
         },
         
         {
            "id": "S1002",
            "firstName": "Kannan",
            "lastName": "Sudhakaran",
            "college": {
               "name": "AMU",
               "location": "Uttar Pradesh"
            }
         },
         
         {
            "id": "S1003",
            "firstName": "Kiran",
            "lastName": "Panigrahi",
            "college": {
               "name": "AMU",
               "location": "Uttar Pradesh"
            }
         }
      ]
   }
}

Mô tả những gì có thể với một hệ thống kiểu

GraphQL được nhập mạnh và các truy vấn dựa trên các trường và kiểu dữ liệu liên quan của chúng. Nếu có loại không khớp trong truy vấn GraphQL, các ứng dụng máy chủ sẽ trả về thông báo lỗi rõ ràng và hữu ích. Điều này giúp gỡ lỗi suôn sẻ và dễ dàng phát hiện lỗi bởi các ứng dụng khách. GraphQL cũng cung cấp các thư viện phía máy khách có thể giúp giảm quá trình chuyển đổi và phân tích cú pháp dữ liệu rõ ràng.

Dưới đây là một ví dụ về kiểu dữ liệu Sinh viênCao đẳng :

type Query {
   students:[Student]
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String
   college:College
}

type College {
   id:ID!
   name:String
   location:String
   rating:Float
   students:[Student]
}

Di chuyển nhanh hơn với các công cụ mạnh mẽ dành cho nhà phát triển

GraphQL cung cấp các công cụ dành cho nhà phát triển phong phú cho các truy vấn tài liệu và thử nghiệm. GraphiQL là một công cụ tuyệt vời tạo ra tài liệu về truy vấn và lược đồ của nó. Nó cũng cung cấp cho một trình soạn thảo truy vấn để kiểm tra các API GraphQL và khả năng hoàn thành mã thông minh trong khi xây dựng các truy vấn.

Trong chương này, chúng ta sẽ tìm hiểu về thiết lập môi trường cho GraphQL. Để thực hiện các ví dụ trong hướng dẫn này, bạn sẽ cần những thứ sau:

  • Máy tính chạy Linux, macOS hoặc Windows.

  • Trình duyệt web, tốt nhất là phiên bản mới nhất của Google Chrome.

  • Đã cài đặt phiên bản Node.js gần đây. Phiên bản LTS mới nhất được khuyến nghị.

  • Visual Studio Code với phần mở rộng GraphQL cho VSCode được cài đặt hoặc bất kỳ trình soạn thảo mã nào bạn chọn.

Cách xây dựng máy chủ GraphQL với Nodejs

Chúng tôi sẽ đi qua một cách tiếp cận chi tiết từng bước để xây dựng máy chủ GraphQL với Nodejs như được hiển thị bên dưới:

Bước 1 - Xác minh các phiên bản Node và Npm

Sau khi cài đặt NodeJs, hãy xác minh phiên bản của nút và npm bằng cách sử dụng các lệnh sau trên thiết bị đầu cuối:

C:\Users\Admin>node -v
v8.11.3

C:\Users\Admin>npm -v
5.6.0

Bước 2 - Tạo một thư mục dự án và mở trong VSCode

Thư mục gốc của dự án có thể được đặt tên là test-app.

Mở thư mục bằng trình chỉnh sửa mã studio trực quan bằng cách sử dụng các hướng dẫn bên dưới -

C:\Users\Admin>mkdir test-app
C:\Users\Admin>cd test-app
C:\Users\Admin\test-app>code.

Bước 3 - Tạo package.json và cài đặt các phụ thuộc

Tạo một tệp package.json sẽ chứa tất cả các phần phụ thuộc của ứng dụng máy chủ GraphQL.

{
   "name": "hello-world-server",
   "private": true,
   "scripts": {
      "start": "nodemon --ignore data/ server.js"
   },
   
   "dependencies": {
      "apollo-server-express": "^1.4.0",
      "body-parser": "^1.18.3",
      "cors": "^2.8.4",
      "express": "^4.16.3",
      "graphql": "^0.13.2",
      "graphql-tools": "^3.1.1"
   },
   
   "devDependencies": {
      "nodemon": "1.17.1"
   }
}

Cài đặt các phụ thuộc bằng cách sử dụng lệnh như dưới đây:

C:\Users\Admin\test-app>npm install

Bước 4 - Tạo cơ sở dữ liệu tệp phẳng trong thư mục dữ liệu

Trong bước này, chúng tôi sử dụng các tệp phẳng để lưu trữ và truy xuất dữ liệu. Tạo dữ liệu thư mục và thêm hai tệpstudents.jsoncolleges.json.

Sau đây là colleges.json tập tin -

[
   {
      "id": "col-101",
      "name": "AMU",
      "location": "Uttar Pradesh",
      "rating":5.0
   },
   
   {
      "id": "col-102",
      "name": "CUSAT",
      "location": "Kerala",
      "rating":4.5
   }
]

Sau đây là students.json tập tin -

[
   {
      "id": "S1001",
      "firstName":"Mohtashim",
      "lastName":"Mohammad",
      "email": "[email protected]",
      "password": "pass123",
      "collegeId": "col-102"
   },
   
   {
      "id": "S1002",
      "email": "[email protected]",
      "firstName":"Kannan",
      "lastName":"Sudhakaran",
      "password": "pass123",
      "collegeId": "col-101"
   },
   
   {
      "id": "S1003",
      "email": "[email protected]",
      "firstName":"Kiran",
      "lastName":"Panigrahi",
      "password": "pass123",
      "collegeId": "col-101"
   }
]

Bước 5 - Tạo lớp truy cập dữ liệu

Chúng ta cần tạo một kho dữ liệu để tải nội dung thư mục dữ liệu. Trong trường hợp này, chúng ta cần các biến tập hợp, sinh viêntrường cao đẳng . Bất cứ khi nào ứng dụng cần dữ liệu, nó sẽ sử dụng các biến thu thập này.

Tạo tệp db.js trong thư mục dự án như sau:

const { DataStore } = require('notarealdb');

const store = new DataStore('./data');

module.exports = {
   students:store.collection('students'),
   colleges:store.collection('colleges')
};

Bước 6 - Tạo tệp lược đồ, schema.graphql

Tạo một tệp giản đồ trong thư mục dự án hiện tại và thêm các nội dung sau:

type Query  {
   test: String
}

Bước 7 - Tạo tệp trình phân giải, giải quyết.js

Tạo tệp trình phân giải trong thư mục dự án hiện tại và thêm nội dung sau:

const Query = {
   test: () => 'Test Success, GraphQL server is up & running !!'
}
module.exports = {Query}

Bước 8 - Tạo Server.js và định cấu hình GraphQL

Tạo tệp máy chủ và định cấu hình GraphQL như sau:

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const db = require('./db');

const port = process.env.PORT || 9000;
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')

const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

app.use(cors(), bodyParser.json());

const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

app.listen(
   port, () => console.info(
      `Server started on port ${port}`
   )
);

Bước 9 - Chạy ứng dụng và kiểm tra bằng GraphiQL

Xác minh cấu trúc thư mục của ứng dụng thử nghiệm dự án như sau:

test-app /
   -->package.json
   -->db.js
   -->data
      students.json
      colleges.json
   -->resolvers.js
   -->schema.graphql
   -->server.js

Chạy lệnh npm start như dưới đây:

C:\Users\Admin\test-app>npm start

Máy chủ đang chạy ở cổng 9000, vì vậy chúng tôi có thể kiểm tra ứng dụng bằng công cụ GraphiQL. Mở trình duyệt và nhập URL http: // localhost: 9000 / graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   Test 
}

Phản hồi từ máy chủ được đưa ra dưới đây:

{
   "data": {
      "test": "Test Success, GraphQL server is running !!"
   }
}

GraphQL là một đặc tả mô tả hoạt động của máy chủ GraphQL. Đây là một tập hợp các nguyên tắc về cách xử lý các yêu cầu và phản hồi như các giao thức được hỗ trợ, định dạng dữ liệu có thể được máy chủ chấp nhận, định dạng của phản hồi do máy chủ trả về, v.v. Yêu cầu do khách hàng đưa ra cho GraphQL máy chủ được gọi là Truy vấn. Một khái niệm quan trọng khác của GraphQL là nông học lớp vận chuyển của nó. Nó có thể được sử dụng với bất kỳ giao thức mạng có sẵn nào như TCP, websocket hoặc bất kỳ giao thức lớp truyền tải nào khác. Nó cũng trung lập với cơ sở dữ liệu, vì vậy bạn có thể sử dụng nó với cơ sở dữ liệu quan hệ hoặc NoSQL.

Máy chủ GraphQL có thể được triển khai bằng cách sử dụng bất kỳ phương pháp nào trong ba phương pháp được liệt kê bên dưới:

  • Máy chủ GraphQL với cơ sở dữ liệu được kết nối
  • Máy chủ GraphQL tích hợp các hệ thống hiện có
  • Phương pháp kết hợp

Máy chủ GraphQL với Cơ sở dữ liệu được Kết nối

Kiến trúc này có Máy chủ GraphQL với cơ sở dữ liệu tích hợp và thường có thể được sử dụng với các dự án mới. Khi nhận được Truy vấn, máy chủ đọc tải trọng yêu cầu và tìm nạp dữ liệu từ cơ sở dữ liệu. Điều này được gọi là giải quyết truy vấn. Phản hồi được trả lại cho khách hàng tuân theo định dạng được chỉ định trong đặc tả GraphQL chính thức.

Trong sơ đồ trên, máy chủ GraphQL và cơ sở dữ liệu được tích hợp trên một nút duy nhất. Máy khách (máy tính để bàn / thiết bị di động) giao tiếp với máy chủ GraphQL qua HTTP. Máy chủ xử lý yêu cầu, tìm nạp dữ liệu từ cơ sở dữ liệu và trả lại cho máy khách.

Máy chủ GraphQL tích hợp các hệ thống hiện có

Cách tiếp cận này hữu ích cho các công ty có cơ sở hạ tầng kế thừa và các API khác nhau. GraphQL có thể được sử dụng để hợp nhất các microservices, cơ sở hạ tầng kế thừa và các API của bên thứ ba trong hệ thống hiện có.

Trong sơ đồ trên, API GraphQL hoạt động như một giao diện giữa máy khách và các hệ thống hiện có. Các ứng dụng khách giao tiếp với máy chủ GraphQL, máy chủ này sẽ giải quyết truy vấn.

Phương pháp kết hợp

Cuối cùng, chúng ta có thể kết hợp hai cách tiếp cận trên và xây dựng một máy chủ GraphQL. Trong kiến ​​trúc này, máy chủ GraphQL sẽ giải quyết mọi yêu cầu nhận được. Nó sẽ truy xuất dữ liệu từ cơ sở dữ liệu được kết nối hoặc từ API tích hợp. Điều này được thể hiện trong hình bên dưới:

Chương này thảo luận về các thành phần GraphQL khác nhau và cách chúng giao tiếp với nhau. Toàn bộ các thành phần ứng dụng có thể được phân biệt như sau:

  • Thành phần phía máy chủ
  • Các thành phần phía máy khách

Thành phần phía máy chủ

Máy chủ GraphQL tạo thành thành phần cốt lõi ở phía máy chủ và cho phép phân tích cú pháp các truy vấn đến từ các ứng dụng máy khách GraphQL. Apollo Server được sử dụng phổ biến nhất để triển khai đặc tả GraphQL. Các thành phần lập trình máy chủ khác bao gồm:

Sr.No. Thông tin cơ bản & Mô tả về Máy chủ
1

Schema

Một lược đồ GraphQL là trung tâm của bất kỳ triển khai máy chủ GraphQL nào và mô tả chức năng có sẵn cho các máy khách kết nối với nó.

2

Query

Truy vấn GraphQL là yêu cầu ứng dụng khách truy xuất dữ liệu từ cơ sở dữ liệu hoặc API kế thừa.

3

Resolver

Trình phân giải cung cấp hướng dẫn để chuyển hoạt động GraphQL thành dữ liệu. Chúng giải quyết truy vấn đến dữ liệu bằng cách xác định các chức năng của trình phân giải.

Các thành phần phía máy khách

Dưới đây là các thành phần phía máy khách -

Sr.No. Công cụ & Mô tả
1

GraphiQL

Giao diện dựa trên trình duyệt để chỉnh sửa và kiểm tra các truy vấn và đột biến GraphQL.

2

ApolloClient

Công cụ tốt nhất để xây dựng các ứng dụng khách GraphQL. Tích hợp tốt với tất cả javascript front-end.

Sơ đồ dưới đây cho thấy một Client-Server architecture. Máy chủ web được xây dựng trên khung NodeJs và Express. Một yêu cầu được gửi đến Máy chủ Apollo GraphQL bằng ứng dụng ReactJS (được xây dựng bằng thư viện Máy khách Apollo) hoặc ứng dụng trình duyệt GraphiQL. Truy vấn sẽ được phân tích cú pháp và xác thực dựa trên một lược đồ được xác định trong máy chủ. Nếu lược đồ yêu cầu vượt qua quá trình xác thực, thì các chức năng của trình phân giải liên quan sẽ được thực thi. Trình phân giải sẽ chứa mã để tìm nạp dữ liệu từ API hoặc cơ sở dữ liệu.

Trong chương này, chúng ta sẽ tạo một API đơn giản trả về một thông điệp chào mừng, HelloWorld và truy cập nó bằng GraphiQL.

Thí dụ

Ví dụ này dựa trên máy chủ NodeJS, Express và Apollo. Chúng ta sẽ học cách đặt tất cả các khái niệm lại với nhau theo các bước sau:

Bước 1 - Thiết lập Express

ExpressJS là một khung ứng dụng web giúp xây dựng các trang web và ứng dụng web. Trong ví dụ này, chúng tôi sẽ xây dựng một API GraphQL trên đầu khung Express.

Bước tiếp theo là tạo một thư mục hello-world-servervà điều hướng đến cùng một thư mục từ thiết bị đầu cuối. Thêm package.json và đặt tên cho gói. Vì gói này chỉ được sử dụng nội bộ nên chúng ta có thể khai báo nó là private.

{
   "name":"hello-world-server",
   "private":true
}

Cài đặt các phụ thuộc cho máy chủ Express như hình dưới đây -

C:\Users\Admin\hello-world-server>npm install express body-parser cors

body-parser là một gói phần mềm trung gian giúp Express xử lý các yêu cầu HTTP Post một cách hiệu quả. cors là một gói phần mềm trung gian khác xử lý việc chia sẻ tài nguyên nguồn gốc chéo.

Tạo một server.js tệp trong thư mục dự án và nhập dòng sau vào đó:

const bodyParser = require('body-parser')
   const cors = require('cors')
   const express = require('express')
   const port = process.env.PORT|| 9000
   const app = express()
   
   //register middleware
   app.use(bodyParser.json() , cors())
   app.listen(port, () =>  console.log(`server is up and running at ${port}`)

Để xác minh xem máy chủ Express có đang hoạt động hay không, hãy thực thi mã sau trong cửa sổ đầu cuối:

C:\Users\Admin\hello-world-server>node server.js

Kết quả sau được hiển thị trong bảng điều khiển máy chủ. Điều này cho thấy rằng máy chủ express đang chạy trên cổng 9000.

server is up and running at 9000

Nếu bạn mở trình duyệt và gõ http://localhost:9000, bạn sẽ nhận được màn hình sau -

Để dừng máy chủ, nhấn Ctrl + C.

Bước 2 - Cài đặt GraphQL và Apollo Server

Bây giờ Express đã được cấu hình, bước tiếp theo là tải xuống các phụ thuộc GraphQL sau:

  • graphql
  • graphql-tools
  • apollo-server-express@1

Chúng tôi sẽ sử dụng máy chủ Apollo v1.0 vì đây là một phiên bản ổn định. Nhập các lệnh sau để cài đặt các phần phụ thuộc này:

C:\Users\Admin\hello-world-server>npm install graphql graphql-tools apollo-server-express@1

Chúng tôi có thể xác minh nếu các phần phụ thuộc này được cài đặt thành công bằng cách kiểm tra package.json tệp mà chúng tôi đã tạo trước đó.

{
   "name": "hello-world-server",
   "private": true,
   
   "dependencies": {
      "apollo-server-express": "^1.4.0",
      "body-parser": "^1.18.3",
      "cors": "^2.8.4",
      "express": "^4.16.3",
      "graphql": "^0.13.2",
      "graphql-tools": "^3.1.1"
   }
}

Bước 3 - Xác định lược đồ

Một lược đồ GraphQL xác định loại đối tượng nào có thể được tìm nạp từ một dịch vụ và nó có những trường nào. Lược đồ có thể được xác định bằng cách sử dụngGraphQL Schema Definition Language. Bây giờ, hãy thêm đoạn mã sau vàoserver.js tập tin -

// Adding Type Definitions
const typeDefinition = `
   type Query  {
      greeting: String
   }

Ở đây, truy vấn chứa thuộc tính lời chào trả về giá trị chuỗi .

Bước 4 - Tạo trình phân giải

Bước đầu tiên trong việc tạo trình phân giải là thêm một số mã để xử lý yêu cầu cho trường lời chào. Điều này được chỉ định trong mộtresolver. Cấu trúc của hàm phân giải phải phù hợp với lược đồ. Thêm đoạn mã sau vàoserver.js tập tin.

// Adding resolver
const  resolverObject = {
   Query : {
      greeting: () => 'Hello GraphQL  From TutorialsPoint !!'
   }
}

Bước thứ hai là liên kết lược đồ và trình phân giải bằng cách sử dụng makeExecutableSchema. Hàm này được xác định trước trong mô-đun graphql-tools. Thêm đoạn mã sau vào server.js tập tin.

const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})

Bước 5 - Xác định các tuyến để tìm nạp dữ liệu từ ứng dụng ReactJS / GraphiQL

Thêm đoạn mã sau vào server.js tập tin -

const {graphqlExpress, graphiqlExpress} = require('apollo-server-express')

   //create routes for graphql and graphiql
   app.use('/graphql',graphqlExpress({schema}))
   
   app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

Hàm graphqlExpress giúp đăng ký lộ trìnhhttp://localhost:9000/graphql. Ứng dụng ReactJS có thể sử dụng điểm cuối này để truy vấn dữ liệu. Tương tự, hàm graphqliExpress giúp đăng ký lộ trìnhhttp://localhost:9000/graphiql. Điều này sẽ được ứng dụng khách trình duyệt GraphiQL sử dụng để kiểm tra API.

Mã server.js hoàn chỉnh như dưới đây:

const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
const port = process.env.PORT||9000
const app = express()

app.use(bodyParser.json() , cors())
const typeDefinition = `
type Query  {
   greeting: String
}`
const  resolverObject = {
   Query : {
      greeting: () => 'Hello GraphQL  From TutorialsPoint !!'
   }
}
const {makeExecutableSchema} = require('graphql-tools')

const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})

const {graphqlExpress,graphiqlExpress} = require('apollo-server-express')

app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
app.listen(port, () =>  console.log(`server is up and running ${port}`))

Bước 6 - Khởi động ứng dụng

Hành hình server.js sử dụng Node.js như sau:

C:\Users\Admin\hello-world-server>node server.js

Bước 7 - Kiểm tra API GraphQL

Mở trình duyệt và nhập http://localhost:9000/graphiql. Trong tab truy vấn của GraphiQL, nhập thông tin sau:

{
   greeting
}

Phản hồi từ máy chủ được đưa ra dưới đây:

{
   "data": {
      "greeting": "Hello GraphQL From TutorialsPoint !!"
   }
}

Hình ảnh sau đây minh họa phản ứng -

Note - Hãy đảm bảo rằng Apollo Server Phiên bản 1.0 đã được sử dụng.

GraphQL là một ngôn ngữ được đánh máy mạnh. Loại Hệ thống xác định các kiểu dữ liệu khác nhau có thể được sử dụng trong ứng dụng GraphQL. Hệ thống kiểu giúp xác định lược đồ, là một hợp đồng giữa máy khách và máy chủ. Các kiểu dữ liệu GraphQL thường được sử dụng như sau:

Sr.No. Loại & Mô tả
1

Scalar

Lưu trữ một giá trị duy nhất

2

Object

Cho biết loại đối tượng nào có thể được tìm nạp

3

Query

Nhập loại điểm đến các loại cụ thể khác

4

Mutation

Điểm vào để thao tác dữ liệu

5

Enum

Hữu ích trong trường hợp bạn cần người dùng chọn từ một danh sách các tùy chọn được chỉ định

Loại vô hướng

Kiểu vô hướng là kiểu dữ liệu nguyên thủy chỉ có thể lưu trữ một giá trị duy nhất. Các loại vô hướng mặc định mà GraphQL cung cấp là:

  • Int - Số nguyên 32-bit đã ký

  • Float - Giá trị dấu chấm động chính xác kép có dấu

  • String - UTF - chuỗi 8 ký tự

  • Boolean - Đúng hay sai

  • ID - Một số nhận dạng duy nhất, thường được sử dụng như một số nhận dạng duy nhất để tìm nạp một đối tượng hoặc làm khóa cho bộ nhớ cache.

Cú pháp để xác định một kiểu vô hướng như sau:

field: data_type

Đoạn mã được đưa ra bên dưới xác định một trường có tên là lời chào trả về giá trị Chuỗi.

greeting: String

Loại đối tượng

Kiểu đối tượng là kiểu phổ biến nhất được sử dụng trong lược đồ và đại diện cho một nhóm trường. Mỗi trường bên trong một kiểu đối tượng ánh xạ tới một kiểu khác, do đó cho phép các kiểu lồng nhau. Nói cách khác, một kiểu đối tượng bao gồm nhiều kiểu vô hướng hoặc nhiều kiểu đối tượng.

Cú pháp để xác định một loại đối tượng được đưa ra dưới đây:

type object_type_name
{
   field1: data_type
   field2:data_type 
   ....
   fieldn:data_type
}

Bạn có thể xem xét đoạn mã sau:

--Define an object type--

type Student {
   stud_id:ID
   firstname: String
   age: Int
   score:Float
}

--Defining a GraphQL schema--  

type Query
{
   stud_details:[Student]
}

Ví dụ ở trên định nghĩa một đối tượng kiểu dữ liệu là Sinh viên. Trường stud_details trong lược đồ Truy vấn gốc sẽ trả về danh sách các đối tượng Sinh viên.

Loại truy vấn

Truy vấn GraphQL được sử dụng để tìm nạp dữ liệu. Nó giống như yêu cầu một tài nguyên trong các API dựa trên REST. Để đơn giản, loại Truy vấn là yêu cầu được gửi từ ứng dụng khách đến máy chủ GraphQL. GraphQL sử dụngSchema Definition Language (SDL)để xác định một Truy vấn. Kiểu truy vấn là một trong nhiều kiểu cấp gốc trong GraphQL.

Cú pháp để xác định một Truy vấn như sau:

type Query {
   field1: data_type
   field2:data_type
   field2(param1:data_type,param2:data_type,...paramN:data_type):data_type
}

Ví dụ về việc xác định một Truy vấn -

type Query  {
   greeting: String
}

Loại đột biến

Các đột biến là các hoạt động được gửi đến máy chủ để create, update hoặc là deletedữ liệu. Chúng tương tự với các động từ PUT, POST, PATCH và DELETE để gọi các API dựa trên REST.

Đột biến là một trong những kiểu dữ liệu cấp cơ sở trong GraphQL. Loại Truy vấn xác định các điểm nhập cho các hoạt động tìm nạp dữ liệu trong khi loại Đột biến chỉ định các điểm nhập cho các hoạt động thao tác dữ liệu.

Cú pháp để xác định loại đột biến được đưa ra dưới đây:

type Mutation {
   field1: data_type
   field2(param1:data_type,param2:data_type,...paramN:data_type):data_type 
}

Ví dụ: chúng ta có thể xác định kiểu đột biến để thêm Sinh viên mới như bên dưới:

type Mutation {
   addStudent(firstName: String, lastName: String): Student
}

Loại Enum

Một Enum tương tự như một kiểu vô hướng. Enums rất hữu ích trong trường hợp giá trị của một trường phải nằm trong danh sách các tùy chọn được chỉ định.

Cú pháp để xác định kiểu Enum là:

type enum_name{
   value1
   value2
}

Đoạn mã sau minh họa cách một loại enum có thể được xác định:

type Days_of_Week{
   SUNDAY
   MONDAY
   TUESDAY
   WEDNESDAY
   THURSDAY
   FRIDAY
   SATURDAY
}

Loại danh sách

Danh sách có thể được sử dụng để biểu diễn một mảng các giá trị của kiểu cụ thể. Danh sách được định nghĩa với một công cụ sửa đổi kiểu [] bao bọc các kiểu đối tượng, vô hướng và enum.

Cú pháp sau có thể được sử dụng để xác định một loại danh sách:

field:[data_type]

Ví dụ dưới đây xác định việc cần làm của loại danh sách -

type Query {
   todos: [String]
}

Loại không thể xóa

Theo mặc định, mỗi loại vô hướng lõi có thể được đặt thành null. Nói cách khác, những kiểu này có thể trả về giá trị của kiểu được chỉ định hoặc chúng có thể không có giá trị. Để ghi đè mặc định này và chỉ định rằng một trường phải được xác định, dấu chấm than (!) Có thể được thêm vào một kiểu. Điều này đảm bảo sự hiện diện của giá trị trong các kết quả được trả về bởi truy vấn.

Cú pháp sau có thể được sử dụng để xác định một trường không thể nullable:

field:data_type!

Trong ví dụ dưới đây, stud_id được khai báo là trường bắt buộc.

type Student {
   stud_id:ID!
   firstName:String
   lastName:String
   fullName:String
   college:College
}

Một lược đồ GraphQL là cốt lõi của bất kỳ triển khai máy chủ GraphQL nào. Nó mô tả chức năng có sẵn cho các ứng dụng khách kết nối với nó. Chúng ta có thể sử dụng bất kỳ ngôn ngữ lập trình nào để tạo lược đồ GraphQL và xây dựng giao diện xung quanh nó.

Thời gian chạy GraphQL xác định một lược đồ dựa trên đồ thị chung để xuất bản các khả năng của dịch vụ dữ liệu mà nó đại diện. Các ứng dụng khách có thể truy vấn lược đồ trong khả năng của nó. Cách tiếp cận này tách khách hàng khỏi máy chủ và cho phép cả hai phát triển và mở rộng quy mô độc lập.

Trong chương này, chúng tôi sử dụng máy chủ Apollo để thực hiện các truy vấn GraphQL. CácmakeExecutableSchema hàm trong graphql-tools giúp bạn liên kết lược đồ và trình phân giải.

Cú pháp hàm makeExecutableSchema

Các makeExecutableSchemahàm nhận một đối số duy nhất {} của kiểu Đối tượng. Cú pháp để sử dụng hàm này được đưa ra dưới đây:

import { makeExecutableSchema } from 'graphql-tools';

const jsSchema = makeExecutableSchema({
   typeDefs,
   resolvers, // optional
   logger, // optional
   allowUndefinedInResolve = false, // optional
   resolverValidationOptions = {}, // optional
   directiveResolvers = null, // optional
   schemaDirectives = null,  // optional
   parseOptions = {},  // optional
   inheritResolversFromInterfaces = false  // optional
});

Sr.No. Mô tả về Thông Số
1

typeDefs

Đây là một đối số bắt buộc. Nó đại diện cho một truy vấn GraphQL dưới dạng một chuỗi UTF-8.

2

Resolvers

Đây là một đối số tùy chọn (đối tượng trống theo mặc định). Điều này có các chức năng xử lý truy vấn.

3

logger

Đây là một đối số tùy chọn và có thể được sử dụng để in lỗi cho bảng điều khiển máy chủ.

4

parseOptions

Đây là một đối số tùy chọn và cho phép tùy chỉnh phân tích cú pháp khi chỉ định typeDefs dưới dạng một chuỗi.

5

allowUndefinedInResolve

Điều này đúng theo mặc định. Khi được đặt thành false, các hàm giải quyết của bạn sẽ tạo ra lỗi nếu chúng trả về không xác định.

6

resolverValidationOptions

Đây là một đối số tùy chọn và chấp nhận một đối tượng có thuộc tính Boolean.

7

inheritResolversFromInterfaces

Đây là một đối số tùy chọn và chấp nhận một đối số Boolean để kiểm tra tính kế thừa của đối tượng giải quyết.

Hình minh họa

Hãy để chúng tôi tạo một ứng dụng đơn giản để hiểu lược đồ này. Thao tác này sẽ tạo một lược đồ để truy vấn danh sách sinh viên từ máy chủ. Dữ liệu sinh viên sẽ được lưu trữ trong một tệp phẳng và chúng tôi sẽ sử dụng một mô-đun nút được gọi lànotarealdb để giả mạo cơ sở dữ liệu và đọc từ tệp phẳng.

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục có tên schema-app. Thay đổi thư mục của bạn thành ứng dụng lược đồ từ thiết bị đầu cuối. Sau đó, làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường để hoàn tất quá trình tải xuống và cài đặt.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tệp trong thư mục dự án, schema-app và thêm mã sau -

type Query {
   greeting:String
   students:[Student]
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   password:String
   collegeId:String
}

Gốc của lược đồ sẽ là kiểu Truy vấn. Truy vấn có hai trường - lời chào và Học sinh trả về Chuỗi và danh sách học sinh tương ứng. Sinh viên được khai báo là một kiểu Đối tượng vì nó chứa nhiều trường. Trường ID được khai báo là không thể null.

Bước 3 - Tạo trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const db = require('./db')
const Query = {
   greeting:() => {
      return "hello from  TutorialsPoint !!!"
   },
   students:() => db.students.list()
}

module.exports = {Query}

Ở đây lời chào và học sinh là người giải quyết xử lý truy vấn. students resolver functiontrả về danh sách sinh viên từ lớp truy cập dữ liệu. Để truy cập các chức năng của trình phân giải bên ngoài mô-đun, đối tượng Truy vấn phải được xuất bằng cách sử dụngmodule.exports.

Bước 4 - Chạy ứng dụng

Tạo tệp server.js và tham khảo bước 8 trong Chương Thiết lập Môi trường. Bước tiếp theo là thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng. Mở trình duyệt và nhập URL,http://localhost:9000/graphiql.

Nhập truy vấn sau vào trình chỉnh sửa -

{
   greeting
   students {
      id
      firstName
      lastName
   }
}

Truy vấn sẽ hiển thị đầu ra như hình dưới đây -

Note- Chúng tôi có thể thay thế sinh viên.json bằng lệnh gọi API RESTful để truy xuất dữ liệu sinh viên hoặc thậm chí là cơ sở dữ liệu thực như MySQL hoặc MongoDB. GraphQL trở thành một lớp bao bọc mỏng xung quanh lớp ứng dụng gốc của bạn để cải thiện hiệu suất.

Resolver là một tập hợp các hàm tạo phản hồi cho truy vấn GraphQL. Nói một cách dễ hiểu, một trình phân giải hoạt động như một trình xử lý truy vấn GraphQL. Mọi hàm phân giải trong lược đồ GraphQL chấp nhận bốn đối số vị trí như được đưa ra bên dưới:

fieldName:(root, args, context, info) => { result }

Dưới đây là một ví dụ về các hàm của trình phân giải:

//resolver function  with no parameters and returning string
greeting:() => {
   return "hello from  TutorialsPoint !!!"
}

//resolver function with no parameters and returning list
students:() => db.students.list()

//resolver function with arguments and returning object
studentById:(root,args,context,info) => {
   return db.students.get(args.id);
}

Dưới đây là các đối số vị trí và mô tả của chúng -

Sr.No. Lập luận & Mô tả
1

root

Đối tượng chứa kết quả trả về từ trình phân giải trên trường mẹ.

2

args

Một đối tượng với các đối số được truyền vào trường trong truy vấn.

3

context

Đây là một đối tượng được chia sẻ bởi tất cả các trình phân giải trong một truy vấn cụ thể.

4

info

Nó chứa thông tin về trạng thái thực thi của truy vấn, bao gồm tên trường, đường dẫn đến trường từ gốc.

Định dạng kết quả trình phân giải

Trình phân giải trong GraphQL có thể trả về các loại giá trị khác nhau như được cung cấp bên dưới:

Sr.No. Lập luận và mô tả
1

null or undefined

điều này cho thấy không thể tìm thấy đối tượng

2

array

điều này chỉ hợp lệ nếu lược đồ chỉ ra rằng kết quả của một trường phải là một danh sách

3

promise

trình phân giải thường thực hiện các hành động không đồng bộ như tìm nạp từ cơ sở dữ liệu hoặc API phụ trợ, vì vậy chúng có thể trả về các lời hứa

4

scalar or object

một trình phân giải cũng có thể trả về các giá trị khác

Hình minh họa

Hãy để chúng tôi tạo một ứng dụng đơn giản để hiểu về trình giải quyết. Thao tác này sẽ tạo lược đồ để truy vấn sinh viên theo id từ máy chủ. Dữ liệu sinh viên sẽ được lưu trữ trong một tệp phẳng và chúng tôi sẽ sử dụng một mô-đun nút được gọi lànotarealdb để giả mạo cơ sở dữ liệu và đọc từ tệp phẳng.

Sau đây là quy trình khôn ngoan từng bước để tạo một ứng dụng đơn giản -

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục có tên resolver-app. Thay đổi thư mục của bạn thànhresolver-apptừ thiết bị đầu cuối. Sau đó, hãy làm theo các bước từ 3 đến 5 trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm tệp schema.graphql trong ứng dụng giải quyết thư mục thư mục dự án và thêm mã sau:

type Query { 
   greeting:String
   students:[Student]
   studentById(id:ID!):Student 
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   password:String
   collegeId:String
}

Tệp lược đồ cho thấy người dùng có thể truy vấn lời chào, học sinhstudentById . Để truy xuất các sinh viên có id cụ thể, chúng tôi sử dụngdata type ID!hiển thị trường định danh duy nhất không thể nullable. Trường sinh viên trả về một mảng sinh viên và lời chào trả về một giá trị chuỗi đơn giản.

Bước 3 - Tạo trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const db = require('./db')
const Query = {
   //resolver function for greeting
   greeting:() => {
      return "hello from  TutorialsPoint !!!"
   },
   
   //resolver function for students returns list
   students:() => db.students.list(),

   //resolver function for studentbyId
   studentById:(root,args,context,info) => {
      //args will contain parameter passed in query
      return db.students.get(args.id);
   }
}
module.exports = {Query}

Ở đây, studentById nhận vào ba tham số. Như đã thảo luận trong chương này, studentId có thể được truy xuất từ ​​args; root sẽ chứa chính đối tượng Query. Để trả về một sinh viên cụ thể, chúng ta cần gọi phương thức get với tham số id trong tuyển tập sinh viên.

Ở đây xin chào, sinh viên, studentById là trình phân giải xử lý truy vấn.students resolver functiontrả về danh sách sinh viên từ lớp truy cập dữ liệu. Để truy cập các chức năng của trình phân giải bên ngoài mô-đun, đối tượng Truy vấn phải được xuất bằng module.exports.

Bước 4 - Chạy ứng dụng

Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập url, http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{  
   studentById(id:"S1001") {
      id
      firstName
      lastName
   }
}

Đầu ra cho truy vấn trên như được hiển thị bên dưới:

{
   "data": {
      "studentById": {
         "id": "S1001",
         "firstName": "Mohtashim",
         "lastName": "Mohammad"
      }
   }
}

Hoạt động GraphQL có thể là hoạt động đọc hoặc ghi. Truy vấn GraphQL được sử dụng để đọc hoặc tìm nạp các giá trị trong khi một đột biến được sử dụng để ghi hoặc đăng các giá trị. Trong cả hai trường hợp, hoạt động là một chuỗi đơn giản mà máy chủ GraphQL có thể phân tích cú pháp và phản hồi với dữ liệu ở định dạng cụ thể. Định dạng phản hồi phổ biến thường được sử dụng cho các ứng dụng web và di động là JSON.

Cú pháp để xác định một truy vấn như sau:

//syntax 1
query query_name{ someField }

//syntax 2
{ someField }

Sau đây là một ví dụ về truy vấn:

//query with name myQuery
query myQuery{
   greeting
}

// query without any name
{
   greeting
}

Rõ ràng từ ví dụ trên rằng từ khóa truy vấn là tùy chọn.

Truy vấn GraphQL giúp giảm tải quá nhiều dữ liệu. Không giống như API Restful, GraphQL cho phép người dùng hạn chế các trường nên được tải về từ máy chủ. Điều này có nghĩa là các truy vấn nhỏ hơn và lưu lượng truy cập qua mạng ít hơn; do đó làm giảm thời gian phản hồi.

Hình minh họa 1 - Mô hình sinh viên truy vấn với trường tùy chỉnh

Trong ví dụ này, chúng tôi có một tập hợp các sinh viên được lưu trữ trong một tệp json. Mỗi mô hình sinh viên có các trường như firstName, lastName và id nhưng không có fullName. Ở đây, chúng ta sẽ thảo luận về cách thực hiện truy vấn để lấy ra fullName của tất cả học sinh. Đối với điều này, chúng ta cần tạo trường fullName trong cả hai trình phân giải lược đồ.

Hãy để chúng tôi xem cách thực hiện minh họa này bằng các bước dưới đây -

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục có tên query-app. Thay đổi thư mục của bạn thànhquery-apptừ thiết bị đầu cuối. Sau đó, hãy làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tệp trong ứng dụng truy vấn thư mục dự án và thêm mã sau:

type Query {
   greeting:String
   students:[Student]
   studentById(id:ID!):Student
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String 
}

Lưu ý rằng không có trường fullName trongstudents.jsontập tin. Tuy nhiên, chúng ta cần lấy tên đầy đủ của sinh viên thông qua một truy vấn. Các FullName , trong trường hợp này sẽ là một lĩnh vực tùy chỉnh mà không có sẵn với nguồn dữ liệu.

Bước 3 - Tạo trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const db = require('./db')
const Query = {
   //resolver function for greeting
   greeting:() => {
      return "hello from  TutorialsPoint !!!"
   },
   
   //resolver function for students returns list
   students:() => db.students.list(),

   //resolver function for studentbyId
   studentById:(root,args,context,info) => {
      //args will contain parameter passed in query
      return db.students.get(args.id);
   }
}

//for each single student object returned,resolver is invoked

const Student = {
   fullName:(root,args,context,info) => {
      return root.firstName+":"+root.lastName
   }
}

module.exports = {Query,Student}

Bước 4 - Chạy ứng dụng

Tạo một server.jstập tin. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh  npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   students{
      id
      fullName
   }
}

Phản hồi cho truy vấn được đưa ra dưới đây:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "fullName": "Mohtashim:Mohammad"
         },
         
         {
            "id": "S1002",
            "fullName": "Kannan:Sudhakaran"
         },
         
         {
            "id": "S1003",
            "fullName": "Kiran:Panigrahi"
         }
      ]
   }
}

Tạo một server.js và thêm mã sau -

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');

const db = require('./db');
const port = 9000;
const app = express();

//loading type definitions from schema file
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})

//loading resolvers
const resolvers = require('./resolvers')

//binding schema and resolver
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})

//enabling cross domain calls and form post
app.use(cors(), bodyParser.json());

//enabling routes
const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

//registering port
app.listen(port, () => console.info(`Server started on port ${port}`));

Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   students{
      id
      fullName
   }
}

Phản hồi cho truy vấn được đưa ra dưới đây:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "fullName": "Mohtashim:Mohammad"
         },
         {
            "id": "S1002",
            "fullName": "Kannan:Sudhakaran"
         },
         {
            "id": "S1003",
            "fullName": "Kiran:Panigrahi"
         }
      ]
   }
}

Hình minh họa 2 - Truy vấn lồng nhau

Hãy để chúng tôi tạo một truy vấn lồng nhau để tìm nạp thông tin chi tiết về sinh viên và thông tin chi tiết về trường đại học của họ. Chúng tôi sẽ làm việc với cùng một thư mục dự án.

Bước 1 - Chỉnh sửa lược đồ

Tệp lược đồ đã có trường sinh viên . Hãy để chúng tôi thêm một trường cao đẳng và xác định loại của nó.

type College {
   id:ID!
   name:String
   location:String
   rating:Float
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String
   college:College
}

Bước 2 - Sửa đổi giải quyết.js

Chúng ta cần thêm một hàm phân giải cao đẳng như bên dưới. Hàm phân giải cao đẳng sẽ được thực thi cho từng đối tượng sinh viên được trả về. Tham số gốc của trình giải quyết trong trường hợp này sẽ chứa học sinh .

const Student = {
   fullName:(root,args,context,info) => {
      return root.firstName+":"+root.lastName
   },
   college:(root) => {
      return db.colleges.get(root.collegeId);
   }
}
module.exports = {Query,Student}

Trình giải quyết trả về đại học của mỗi học sinh bằng cách gọi phương thức get của tuyển tập đại học và vượt qua collegeId . Chúng tôi có mối quan hệ liên kết giữa Sinh viên và Cao đẳng thông qua collegeId .

Bước 3 - Kiểm tra ứng dụng

Mở cửa sổ đầu cuối và điều hướng đến thư mục dự án. Gõ lệnh -npm start. Khởi chạy trình duyệt và nhập URLhttp://localhost:9000/graphiql.

Nhập truy vấn sau vào cửa sổ GraphiQL -

{
   students{
      id
      firstName
      college {
         id
         name
         location
         rating
      }
   }
}

Câu trả lời cho truy vấn như dưới đây:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim",
            "college": {
               "id": "col-102",
               "name": "CUSAT",
               "location": "Kerala",
               "rating": 4.5
            }
         },
         
         {
            "id": "S1002",
            "firstName": "Kannan",
            "college": {
               "id": "col-101",
               "name": "AMU",
               "location": "Uttar Pradesh",
               "rating": 5
            }
         },
         
         {
            "id": "S1003",
            "firstName": "Kiran",
            "college": {
               "id": "col-101",
               "name": "AMU",
               "location": "Uttar Pradesh",
               "rating": 5
            }
         }
      ]
   }
}

Biến truy vấn là gì?

Nếu truy vấn có một số giá trị động được chuyển, thì hãy biểu diễn các giá trị động này bằng cách sử dụng các biến. Do đó, truy vấn có thể được sử dụng lại bởi các ứng dụng khách.

Hình minh họa

Hãy để chúng tôi tạo một ứng dụng đơn giản để hiểu biến truy vấn.

Bước 1 - Chỉnh sửa tệp lược đồ

Thêm trường sayHello nhận tham số chuỗi và trả về một chuỗi. Các giá trị tên sẽ là động trong ứng dụng khách.

type Query {
   sayHello(name:String!):String
}

Bước 2 - Chỉnh sửa tệp Resolutionver.js

Thêm trình phân giải sayHello có tham số như bên dưới:

sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`

Bước 3 - Khai báo biến truy vấn trong GraphiQL

Một biến được khai báo với $ theo sau là tên của biến. Ví dụ: $ myname_Variable.

Khi $ myname_Variable được khai báo, nó phải được sử dụng với cú pháp truy vấn được đặt tên. Truy vấn, myQuery nhận giá trị chuỗi và chuyển nó đến sayHello như hình dưới đây:

query myQuery($myname_Variable:String!) { sayHello(name:$myname_Variable)
}

Đặt giá trị cho $ myname_Variable dưới dạng đối tượng JSON trong phần Biến truy vấn của máy khách GraphiQL.

{
   "myname_Variable": "Mohtashim"
}

Đầu ra của đoạn mã trên như sau:

{
   "data": {
      "sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
   }
}

Cách sử dụng Biến truy vấn với Enum

Hãy để chúng tôi xem cách sử dụng biến truy vấn khi tham số trường là enum type.

Bước 1 - Chỉnh sửa tệp schema.graphql

enum ColorType {
   RED
   BLUE
   GREEN
}

type Query {
   setFavouriteColor(color:ColorType):String
}

Hàm setFavouriteColor nhận enum làm đầu vào và trả về một giá trị chuỗi.

Bước 2 - Chỉnh sửa tệp giải quyết.js

Hàm phân giải setFavouriteColorgốcargs . Giá trị enum được truyền cho hàm trong thời gian chạy có thể được truy cập thông qua tham số args.

setFavouriteColor:(root,args) => {
   return  "Your Fav Color is :"+args.color;
}

Bước 3 - Khai báo một biến truy vấn trong GraphiQL

Truy vấn được đặt tên query_to_setColorlấy một biến tên color_variable của ColorType. Biến này được chuyển cho phương thức setFavouriteColor.

query query_to_setColor($color_variable:ColorType) {
   setFavouriteColor(color:$color_variable)
}

Trong phần biến truy vấn của GraphiQL, hãy nhập mã sau:

{
   "color_variable":"RED"
}

Phản hồi được hiển thị bên dưới -

{
   "data": {
      "setFavouriteColor": "Your Fav Color is: RED"
   }
}

Trong chương này, chúng ta sẽ tìm hiểu các truy vấn đột biến trong GraphQL.

Truy vấn đột biến sửa đổi dữ liệu trong kho dữ liệu và trả về một giá trị. Nó có thể được sử dụng để chèn, cập nhật hoặc xóa dữ liệu. Các đột biến được xác định là một phần của lược đồ.

Cú pháp của một truy vấn đột biến được đưa ra dưới đây:

mutation{
   someEditOperation(dataField:"valueOfField"):returnType
}

Hình minh họa

Hãy để chúng tôi hiểu cách thêm hồ sơ sinh viên mới vào kho dữ liệu bằng cách sử dụng truy vấn đột biến.

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục dự án theo tên ứng dụng. Thay đổi thư mục của bạn thành ứng dụng đột biến từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo tệp schema.graphql

Thêm vào schema.graphql tệp trong thư mục dự án ứng dụng đột biến và thêm mã sau:

type Query {
   greeting:String
}

type Mutation {
   createStudent(collegeId:ID,firstName:String,lastName:String):String
}

Lưu ý rằng hàm createStudent trả về kiểu Chuỗi. Đây là số nhận dạng (ID) duy nhất được tạo sau khi tạo sinh viên.

Bước 3 - Tạo tệp Resolutionver.js

Tạo một tệp giải quyết tệp tin.js trong thư mục dự án và thêm mã sau:

const db = require('./db')
const Mutation = {
   createStudent:(root,args,context,info) => {
      return db.students.create({collegeId:args.collegeId,
      firstName:args.firstName,
      lastName:args.lastName})
   }
}
const Query = {
   greeting:() => "hello"
}

module.exports = {Query,Mutation}

Hàm đột biến trỏ đến tập hợp sinh viên trong kho dữ liệu. Để thêm một học sinh mới , hãy gọi phương thức tạo trong bộ sưu tập học sinh. Các args đối tượng sẽ chứa các thông số được thông qua trong truy vấn. Phương thức tạo tập hợp sinh viên sẽ trả về id của một đối tượng sinh viên mới được tạo.

Bước 4 - Chạy ứng dụng

Tạo một server.jstập tin. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Bước tiếp theo là mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

//college Id should be matched with data from colleges.json for easy retrieval

mutation {
   createStudent(collegeId:"col-2",firstName:"Tim",lastName:"George")
}

Truy vấn trên sẽ tạo một đối tượng student trong tệp student.json. Truy vấn sẽ trả về một số nhận dạng duy nhất. Phản hồi của truy vấn như được hiển thị bên dưới:

{
   "data": {
      "createStudent": "SkQtxYBUm"
   }
}

Để xác minh xem đối tượng student có được tạo hay không, chúng ta có thể sử dụng truy vấn studentById. Bạn cũng có thể mở tệp student.json từ thư mục dữ liệu để xác minh id.

Để sử dụng truy vấn studentById, hãy chỉnh sửa schema.graphql như dưới đây -

type Query {
   studentById(id:ID!):Student
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   collegeId:String
}

Chỉnh sửa resolver.js tệp như được cung cấp bên dưới -

const db = require('./db')
const Query = {
   studentById:(root,args,context,info) => {
      return db.students.get(args.id);
   }
}

const Mutation = {
   createStudent:(root,args,context,info) => {
      return db.students.create({collegeId:args.collegeId,
      firstName:args.firstName,
      lastName:args.lastName})
   }
}

module.exports = {Query,Mutation}

Dưới đây là truy vấn để lấy sinh viên theo id duy nhất được trả về từ truy vấn đột biến -

{
    studentById(id:"SkQtxYBUm") {
    id
    firstName
    lastName
  }
}

Phản hồi từ máy chủ như sau:

{
   "data": {
      "studentById": {
         "id": "SkQtxYBUm",
         "firstName": "Tim",
         "lastName":"George"
      }
   }
}

Trả lại một đối tượng trong đột biến

Cách tốt nhất là trả lại một đối tượng ở dạng đột biến. Ví dụ: ứng dụng khách muốn tìm nạp thông tin chi tiết của sinh viên và trường đại học. Trong trường hợp này, thay vì đưa ra hai yêu cầu khác nhau, chúng ta có thể tạo một truy vấn trả về một đối tượng chứa các sinh viên và thông tin chi tiết về trường đại học của họ.

Bước 1 - Chỉnh sửa tệp lược đồ

Thêm một phương pháp mới có tên addStudent trả về đối tượng trong loại đột biến của schema.graphql.

Hãy để chúng tôi tìm hiểu cách truy cập thông tin chi tiết về trường đại học thông qua chi tiết sinh viên. Thêm loại đại học trong tệp giản đồ.

type Mutation {
   addStudent_returns_object(collegeId:ID,firstName:String,lastName:String):Student

   createStudent(collegeId:ID,firstName:String,lastName:String):String
}

type College {
   id:ID!
   name:String
   location:String
   rating:Float
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   college:College
}

Bước 2 - Cập nhật tệp Resolutionvers.js

Cập nhật tệp resolvers.js trong thư mục dự án và thêm mã sau:

const Mutation = {
   createStudent:(root,args,context,info) => {

      return db.students.create({
         collegeId:args.collegeId,
         firstName:args.firstName,
         lastName:args.lastName
      })
   },
   
   // new resolver function
   addStudent_returns_object:(root,args,context,info) => {
      const id = db.students.create({
         collegeId:args.collegeId,
         firstName:args.firstName,
         lastName:args.lastName
      })

      return db.students.get(id)
   }
}

//for each single student object returned,resolver is invoked
const Student = {
   college:(root) => {
      return db.colleges.get(root.collegeId);
   }
}

module.exports = {Query,Student,Mutation}

Bước 3 - Khởi động Máy chủ và Nhập Truy vấn Yêu cầu trong GraphiQL

Tiếp theo, chúng tôi sẽ khởi động máy chủ và yêu cầu truy vấn trong GraphiQL với đoạn mã sau:

mutation {
   addStudent_returns_object(collegeId:"col-101",firstName:"Susan",lastName:"George") {
      id
      firstName
      college{
         id
         name
      }
   }
}

Truy vấn trên thêm một sinh viên mới và truy xuất đối tượng student cùng với đối tượng college. Điều này tiết kiệm các chuyến đi vòng đến máy chủ.

Câu trả lời như sau:

{
   "data": {
      "addStudent_returns_object": {
         "id": "rklUl08IX",
         "firstName": "Susan",
         "college": {
            "id": "col-101",
            "name": "AMU"
         }
      }
   }
}

Trong khi thêm hoặc sửa đổi dữ liệu, điều quan trọng là phải xác thực đầu vào của người dùng. Ví dụ, chúng ta có thể cần đảm bảo rằng giá trị của một trường luôn không rỗng. Chúng ta có thể sử dụng! (non-nullable) nhập điểm đánh dấu trong GraphQL để thực hiện xác nhận như vậy.

Cú pháp để sử dụng ! đánh dấu loại như được đưa ra bên dưới -

type TypeName {
   field1:String!,
   field2:String!,
   field3:Int!
}

Cú pháp trên đảm bảo rằng tất cả các trường không rỗng.

Nếu chúng tôi muốn triển khai các quy tắc bổ sung như kiểm tra độ dài của một chuỗi hoặc kiểm tra xem một số có nằm trong một phạm vi nhất định hay không, chúng tôi có thể xác định trình xác thực tùy chỉnh. Logic xác thực tùy chỉnh sẽ là một phần của chức năng trình phân giải. Hãy để chúng tôi hiểu điều này với sự trợ giúp của một ví dụ.

Hình minh họa - Triển khai Trình xác thực tùy chỉnh

Hãy để chúng tôi tạo một biểu mẫu đăng ký với xác thực cơ bản. Biểu mẫu sẽ có các trường email, tên và mật khẩu.

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục có tên validation-app. Thay đổi thư mục thành ứng dụng xác thực từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tập tin trong thư mục dự án validation-app và thêm mã sau -

type Query {
   greeting:String
}

type Mutation {
   signUp(input:SignUpInput):String
}

input SignUpInput {
   email:String!,
   password:String!,
   firstName:String!
}

Note- Chúng ta có thể sử dụng kiểu nhập SignUpInput để giảm số lượng tham số trong hàm signUp. Vì vậy, hàm signUp chỉ nhận một tham số kiểu SignUpInput.

Bước 3 - Tạo trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const Query = {
   greeting:() => "Hello"
}

const Mutation ={
   signUp:(root,args,context,info) => {

      const {email,firstName,password} = args.input;

      const emailExpression = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      
      const isValidEmail =  emailExpression.test(String(email).toLowerCase())
      if(!isValidEmail)
      throw new Error("email not in proper format")

      if(firstName.length > 15)
      throw new Error("firstName should be less than 15 characters")

      if(password.length < 8 )
      throw new Error("password should be minimum 8 characters")
      
      return "success";
   }
}
module.exports = {Query,Mutation}

Chức năng giải quyết, signUp chấp nhận các tham số email, mật khẩu và firstName. Chúng sẽ được chuyển qua biến đầu vào để nó có thể được truy cập thông qua args.input.

Bước 4 - Chạy ứng dụng

Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sẽ sử dụng GraphiQL làm client để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

mutation doSignUp($input:SignUpInput) { signUp(input:$input)
}

Vì đầu vào cho hàm đăng ký là một kiểu phức tạp, chúng ta cần sử dụng các biến truy vấn trong graphiql. Đối với điều này, trước tiên chúng ta cần đặt tên cho truy vấn và gọi nó là doSignUp, $ input là một biến truy vấn.

Biến truy vấn sau phải được nhập vào tab biến truy vấn của graphiql -

{
   "input":{
      "email": "abc@abc",
      "firstName": "kannan",
      "password": "pass@1234"
   }
}

Mảng lỗi chứa các chi tiết về lỗi xác thực như được hiển thị bên dưới:

{
   "data": {
      "signUp": null
   },
   
   "errors": [
      {
         "message": "email not in proper format",
         "locations": [
            {
               "line": 2,
               "column": 4
            }
         ],
         "path": [
            "signUp"
         ]
      }
   ]
}

Chúng ta phải nhập một đầu vào thích hợp cho mỗi trường như được cung cấp bên dưới:

{
   "input":{
      "email": "[email protected]",
      "firstName": "kannan",
      "password": "pass@1234"
   }
}

Câu trả lời như sau:

{
   "data": {
      "signUp": "success"
   }
}

Ở đây, trong truy vấn dưới đây, chúng tôi không chỉ định bất kỳ mật khẩu nào.

{
   "input":{
      "email": "[email protected]",
      "firstName": "kannan"
   }
}

Nếu trường bắt buộc không được cung cấp, thì máy chủ qraphql sẽ hiển thị lỗi sau:

{
   "errors": [
      {
         "message": "Variable \"$input\" got invalid value {\"email\":\"[email protected]\",\"firstName\":\"kannan\"}; Field value.password of required type String! was not provided.",
         "locations": [
            {
               "line": 1,
               "column": 19
            }
         ]
      }
   ]
}

Ứng dụng web gửi và truy xuất dữ liệu không đồng bộ (ở chế độ nền). AJAX cho phép các trang web tải nội dung lên màn hình mà không cần làm mới trang. jQuery cung cấp một số phương thức cho chức năng AJAX, do đó giúp sử dụng AJAX dễ dàng hơn. Trong chương này, chúng ta sẽ tìm hiểu cách tích hợp GraphQL với jQuery.

Xem xét một ứng dụng sử dụng kiến ​​trúc máy chủ khách hàng. Chúng tôi có thể xây dựng một trang web giao diện người dùng yêu cầu dữ liệu từ máy chủ GraphQL. Trang web sẽ thực hiện các cuộc gọi AJAX bằng jQuery đến máy chủ GraphQL.

Để tích hợp GraphQL với JQuery, hãy để chúng tôi kiểm tra tiêu đề yêu cầu GraphiQL và hiểu các tham số yêu cầu.

Bắt đầu hello-worldứng dụng (tham khảo chương 6 để biết hình minh họa liên quan). Nhập truy vấn graphql {câu chào} vào cửa sổ GraphiQL. Nhấp chuột phải và kiểm tra hoặc nhấn (ctrl + shift + I) trên chrome để chuyển đến tab mạng như hình dưới đây -

Từ đơn giản hello-world ví dụ, chúng ta có thể hiểu rằng http method được sử dụng là POST. Bây giờ trong trình duyệt, cuộn xuống phần tiêu đề để xem  tải trọng yêu cầu .

Khi bạn nhấp vào view code, bạn sẽ thấy như sau trong phần tải trọng yêu cầu của chrome.

{"query":"{\n  greeting\n}","variables":null,"operationName":null}

Cũng lưu ý URL yêu cầu, http://localhost:9000/graphql cái đó sẽ được gọi từ ứng dụng khách.

Hình minh họa

Hãy để chúng tôi hiểu cách tích hợp GraphQL với JQuery bằng quy trình từng bước.

Thiết lập máy chủ

Chúng ta sẽ học cách thiết lập máy chủ bằng các bước sau:

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục có tên jquery-server-app. Thay đổi thư mục của bạn thành jquery-server-app từ terminal. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm tệp schema.graphql trong thư mục dự án jquery-server-app và thêm mã sau -

type Query
{
   greeting: String
   sayHello(name:String!):String
}

Tệp đã xác định hai truy vấn greetingsayHello. Truy vấn sayHello chấp nhận một tham số chuỗi và trả về một chuỗi khác. Tham số của hàm sayHello () không phải là giá trị rỗng.

Bước 3 - Tạo trình phân giải

Tạo một tệp giải quyết tệp tin.js trong thư mục dự án và thêm mã sau:

const Query =
{
   greeting: () => 'Hello GraphQL  From TutorialsPoint !!' ,
   sayHello:(root,args,context,info) =>  `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}

Đây, greetingsayHellolà hai trình phân giải. Trong trình giải quyết sayHello, giá trị được truyền cho tham số tên có thể được truy cập thông qua các args. Để truy cập các chức năng của trình phân giải bên ngoài mô-đun, đối tượng Truy vấn phải được xuất bằng cách sử dụngmodule.exports.

Bước 4 - Chạy ứng dụng

Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   greeting,
   sayHello(name:"Mohtashim")
}

Phản hồi từ máy chủ như dưới đây:

{
   "data": {
      "greeting": "Hello GraphQL From TutorialsPoint !!",
      "sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
   }
}

Thiết lập Khách hàng

Vì chúng ta đã thiết lập máy chủ rồi, bây giờ chúng ta sẽ học cách thiết lập máy khách.

Bước 1 - Tạo một thư mục mới jquery-client-app bên ngoài thư mục dự án hiện tại

Đầu tiên, chúng tôi sẽ tạo một thư mục có tên jquery-client-app bên ngoài thư mục dự án.

Bước 2 - Tạo một Trang HTML index.html để Tích hợp jQuery

Chúng tôi sẽ tạo một ứng dụng khách trong jquery và gọi cả hai phương thức. Sau đây là mã cho index.html tập tin. Các index.html trang gửi yêu cầu đến máy chủ khi các nút - GreetSayHellođược nhấp vào. Chúng tôi sẽ thực hiện yêu cầu không đồng bộ bằng cách sử dụng hàm $ .ajax ().

<!DOCTYPE html>
<html>
   <head>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script>
         $(document).ready(function() { $("#btnSayhello").click(function() {

               const name = $("#txtName").val(); console.log(name); $("#SayhelloDiv").html('loading....');

               $.ajax({url: "http://localhost:9000/graphql", contentType: "application/json",type:'POST', data: JSON.stringify({ query:`{ sayHello(name:"${name}")}`
                  }),
                  success: function(result) {
                     console.log(JSON.stringify(result))
                     $("#SayhelloDiv").html("<h1>"+result.data.sayHello +"</h1>"); } }); }); $("#btnGreet").click(function() {
               $("#greetingDiv").html('loading....'); //https://kannan-first-graphql-app.herokuapp.com/graphql $.ajax({url: "http://localhost:9000/graphql",
                  contentType: "application/json",
                  type:'POST',
                  data: JSON.stringify({
                     query:`{greeting}`
                  }),
                  success: function(result) {
                     $("#greetingDiv").html("<h1>"+result.data.greeting+"</h1>");
                  }
               });
            });
         });
      </script>
   </head>
   
   <body>
      <h1>Jquery Client </h1>

      <hr/>
      <section>
         <button id = "btnGreet">Greet</button>
         <br/> <br/>
         <div id = "greetingDiv"> </div>
      </section>
      
      <br/> <br/> <br/>
      <hr/>

      <section>
         Enter a name:<input id = "txtName" type = "text" value = "kannan"/>
         <button id = "btnSayhello">SayHello</button>
         <div id = "SayhelloDiv"> </div>
      </section>
   </body>
</html>

Mở tệp này trong trình duyệt và nhấp vào nút để xem phản hồi. Đầu ra sẽ như dưới đây:

React là một thư viện Javascript để xây dựng giao diện người dùng. Chương này giải thích cách người ta có thể tích hợp GraphQL với một ứng dụng React.

Hình minh họa

Cách nhanh nhất để thiết lập dự án phản ứng là sử  dụng  công cụ Tạo ứng dụng phản ứng . Trong các phần tiếp theo, chúng ta sẽ học cách thiết lập cả Máy chủ và Máy khách.

Thiết lập máy chủ

Để thiết lập Máy chủ, hãy làm theo các bước sau:

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục react-server-app. Thay đổi thư mục của bạn thành react-server-app từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tập tin trong thư mục dự án react-server-app và thêm mã sau -

type Query
{
   greeting: String
   sayHello(name:String!):String
}

Tệp đã xác định hai truy vấn - lời chào và lời chào. Truy vấn sayHello chấp nhận một tham số chuỗi và trả về một chuỗi khác. Tham số của hàm sayHello () không phải là giá trị rỗng.

Bước 3 - Tạo trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const Query =
{
   greeting: () => 'Hello GraphQL  From TutorialsPoint !!' ,
   sayHello:(root,args,context,info) =>  `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}

Ở đây lời chào và câu nói Xin chào là hai cách giải quyết. Trong trình phân giải sayHello, giá trị được truyền cho tham số name có thể được truy cập thông qua các args. Để truy cập các chức năng của trình phân giải bên ngoài mô-đun, đối tượng Truy vấn phải được xuất bằng module.exports.

Bước 4 - Chạy ứng dụng

Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   greeting,
   sayHello(name:"Mohtashim")
}

Phản hồi từ máy chủ được đưa ra dưới đây:

{
   "data": {
      "greeting": "Hello GraphQL  From TutorialsPoint !!",
      "sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
   }
}

Thiết lập Khách hàng

Mở một thiết bị đầu cuối mới cho khách hàng. Thiết bị đầu cuối của máy chủ phải được duy trì chạy trước khi thực thi ứng dụng khách. Ứng dụng React sẽ chạy trên cổng số 3000 và ứng dụng máy chủ trên cổng số 9000.

Bước 1 - Tạo dự án React hello-world-client

Trong thiết bị đầu cuối của máy khách, nhập lệnh sau:

npx create-react-app hello-world-client

Điều này sẽ cài đặt mọi thứ cần thiết cho một ứng dụng phản ứng điển hình. Cácnpx tiện ích và create-react-appcông cụ tạo một dự án với tên hello-world-client. Sau khi cài đặt xong, hãy mở dự án trong VSCode.

Bước 2 - Bắt đầu hello-world-client

Thay đổi đường dẫn thư mục hiện tại trong terminal thành hello-world-client. Nhập npm start để khởi chạy dự án. Thao tác này sẽ chạy một máy chủ phát triển ở cổng 3000 và sẽ tự động mở trình duyệt và tải trang chỉ mục.

Điều này được hiển thị trong ảnh chụp màn hình dưới đây -

Bước 3 - Sửa đổi thành phần ứng dụng

Trong thư mục App.js bên trong src, thêm hai chức năng, một để tải lời chào và một chức năng khác để tải tin nhắn sayHello.

Sau đây là hàm loadGreeting gửi truy vấn GraphQL cho lời chào.

async function loadGreeting() {
   const response = await fetch('http://localhost:9000/graphql', {
      method:'POST',

      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:'{greeting}'})
   })

   const rsponseBody = await response.json();
   return rsponseBody.data.greeting;

   console.log("end of function")
}

Sau đây là loadSayhello hàm gửi truy vấn GraphQL cho sayHello -

async function  loadSayhello(name) {
   const response = await fetch('http://localhost:9000/graphql', {
      method:'POST',
      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
   })
}

Hoàn chỉnh App.js tệp được hiển thị bên dưới -

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

async function loadGreeting() {
   const response =  await fetch('http://localhost:9000/graphql', {
      method:'POST',
      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:'{greeting}'})
   })
   const rsponseBody =  await response.json();
   return rsponseBody.data.greeting;
   console.log("end of function")
}

async function  loadSayhello(name) {
   const response =  await fetch('http://localhost:9000/graphql', {
      method:'POST',
      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
   })
   const rsponseBody =  await response.json();
   return rsponseBody.data.sayHello;
}

class App extends Component {
   constructor(props) {
      super(props);
      this.state =  {greetingMessage:'',sayHelloMessage:'',userName:''}
      this.updateName =  this.updateName.bind(this);
      this.showSayHelloMessage =  this.showSayHelloMessage.bind(this);
      this.showGreeting =  this.showGreeting.bind(this);
   }
   
   showGreeting() {
      loadGreeting().then(g => this.setState({greetingMessage:g+" :-)"}))
   }
   
   showSayHelloMessage() {
      const name = this.state.userName;
      console.log(name)
      loadSayhello(name).then(m => this.setState({sayHelloMessage:m}))
   }
   
   updateName(event) {
      this.setState({userName:event.target.value})
   }
   render() {
      return (
         <div className = "App">
            <header className = "App-header">
               <img src = {logo} className = "App-logo" alt = "logo" />
               <h1 className = "App-title">Welcome to React</h1>
            </header>
            <br/><br/>
            <section>
               <button id = "btnGreet" onClick = {this.showGreeting}>Greet</button>
               <br/> <br/>
               <div id = "greetingDiv">
                  <h1>{this.state.greetingMessage}</h1>
               </div>
            </section>
            
            <hr/>
            
            <section>
               Enter a name:<input id = "txtName" type = "text" onChange = {this.updateName}
               value = {this.state.userName}/>
               <button id = "btnSayhello" onClick = {this.showSayHelloMessage}>SayHello</button>
               <br/>
               user name is:{this.state.userName}    <br/>
               <div id = "SayhelloDiv">
                  <h1>{this.state.sayHelloMessage}</h1>
               </div>
            </section>
         </div>
      );
   }
}

export default App;

Khi cả hai ứng dụng đang chạy, hãy nhấp vào nút chào. Tiếp theo, nhập tên vào hộp văn bản và nhấp vào nút sayHello. Đầu ra sẽ như dưới đây:

Chúng tôi đã sử dụng Apollo Server để xây dựng đặc tả graphql ở phía máy chủ. Rất nhanh chóng và dễ dàng để xây dựng máy chủ GraphQL sẵn sàng sản xuất. Bây giờ chúng ta hãy hiểu về phía khách hàng.

Apollo Client là cách tốt nhất để sử dụng GraphQL để xây dựng các ứng dụng khách. Ứng dụng khách được thiết kế để giúp nhà phát triển nhanh chóng xây dựng một giao diện người dùng tìm nạp dữ liệu bằng GraphQL và có thể được sử dụng với bất kỳ giao diện người dùng JavaScript nào.

Apollo Client hỗ trợ các nền tảng sau:

Sr.No. Nền tảng & Khuôn khổ
1

Javascript

React, Angular, Vue, Meteor, Ember

2

WebComponents

Polyme, lit-apollo

3

Native Mobile

Android gốc với Java, iOS gốc với Swift

Bộ nhớ đệm là một trong những tính năng chính của Apollo Client. apollo-boost là một gói tiện lợi mang lại một loạt các phụ thuộc khác.

Hình minh họa

Hãy để chúng tôi xem cách sử dụng Apollo Client để tạo các ứng dụng khách bằng các bước sau:

Thiết lập máy chủ

Chúng tôi phải làm theo các bước dưới đây để thiết lập một máy chủ -

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục apollo-server-app. Thay đổi thư mục của bạn thành apollo-server-app từ thiết bị đầu cuối. Sau đó, hãy làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tập tin trong thư mục dự án apollo-server-app và thêm mã sau -

type Query
{
   students:[Student]
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   college:College
}

type College {
   id:ID!
   name:String
   location:String
   rating:Float
}

Bước 3 - Thêm trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

const db = require('./db')

const Query = {
   //resolver function for students returns list
   students:() => db.students.list(),
}

const Student = {
   college:(root) => {
      return db.colleges.get(root.collegeId);
   }
}
module.exports = {Query,Student}

Bước 4 - Chạy ứng dụng

Tạo một server.jstập tin. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh  npm start  trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sẽ sử dụng GraphiQL làm client để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình soạn thảo.

{
   students{
      id
      firstName
      college{
         name
      }
   }
}

Câu trả lời cho truy vấn như dưới đây:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim",
            "college": {
               "name": "CUSAT"
            }
         },
         
         {
            "id": "S1002",
            "firstName": "Kannan",
            "college": {
               "name": "AMU"
            }
         },
         
         {
            "id": "S1003",
            "firstName": "Kiran",
            "college": {
               "name": "AMU"
            }
         }
      ]
   }
}

Thiết lập Khách hàng

Mở một thiết bị đầu cuối mới cho khách hàng. Thiết bị đầu cuối của máy chủ phải được duy trì chạy trước khi thực thi ứng dụng khách. Ứng dụng React sẽ chạy trên cổng số 3000 và ứng dụng máy chủ trên cổng số 9000.

Bước 1 - Tạo ứng dụng React

Trong thiết bị đầu cuối của máy khách, nhập lệnh sau:

npx create-react-app hello-world-client

Điều này sẽ cài đặt mọi thứ cần thiết cho một ứng dụng phản ứng điển hình. Tiện ích npx và công cụ create-react-app tạo một dự án với tênhello-world-client. Sau khi cài đặt xong, hãy mở dự án trong VSCode.

Bước 2 - Bắt đầu hello-world-client

Thay đổi đường dẫn thư mục hiện tại trong thiết bị đầu cuối thành hello-world-client. Nhập npm start để khởi chạy dự án. Thao tác này sẽ chạy một máy chủ phát triển ở cổng 3000 và sẽ tự động mở trình duyệt và tải trang chỉ mục.

Điều này được hiển thị trong ảnh chụp màn hình dưới đây -

Bước 3 - Cài đặt thư viện khách hàng Apollo

Để cài đặt Ứng dụng khách Apollo, hãy mở một thiết bị đầu cuối mới và ở trong đường dẫn thư mục dự án hiện tại. Gõ lệnh sau:

npm install apollo-boost graphql

Thao tác này sẽ tải xuống các thư viện graphql cho phía máy khách và cả gói Apollo Boost. Chúng tôi có thể kiểm tra chéo điều này bằng cách nhập chế độ xem npm trong phần phụ thuộc apollo-boost. Điều này sẽ có nhiều phụ thuộc như hình dưới đây -

{
   'apollo-cache': '^1.1.15',
   'apollo-cache-inmemory': '^1.2.8',
   'apollo-client': '^2.4.0',
   'apollo-link': '^1.0.6',
   'apollo-link-error': '^1.0.3',
   'apollo-link-http': '^1.3.1',
   'apollo-link-state': '^0.4.0',
   'graphql-tag': '^2.4.2'
}

Chúng ta có thể thấy rõ rằng thư viện Apollo-Client đã được cài đặt.

Bước 4 - Sửa đổi thành phần ứng dụng trong tệp index.js

Với Apollo Client, chúng tôi có thể gọi trực tiếp máy chủ mà không cần sử dụng API tìm nạp. Ngoài ra, các truy vấn và đột biến không nên được nhúng vào một chuỗi được tạo với ký hiệu đánh dấu lùi. Điều này là do,gqlhàm phân tích cú pháp trực tiếp các truy vấn. Điều này có nghĩa là, một lập trình viên có thể viết trực tiếp truy vấn theo cách tương tự khi viết truy vấn trong công cụ GraphiQL. gql là một chức năng thẻ sẽ phân tích cú pháp chuỗi mẫu được viết bằng ký hiệu đánh dấu phía sau thành đối tượng truy vấn graphql. Phương thức truy vấn Apollo Client trả về một lời hứa.

Đoạn mã sau đây cho thấy cách nhập Apollo Client -

import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'

const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
   link: new HttpLink({uri:endPointUrl}),
   cache:new InMemoryCache()
});

Trong chương trước, chúng ta đã thảo luận về cách sử dụng API tìm nạp cho các yêu cầu HTTP. Đoạn mã sau cho biết cách sử dụnggqlchức năng. CácloadStudentsAsync hàm sử dụng máy khách graphql để truy vấn máy chủ.

async function loadStudentsAsync() {
   const query = gql`
   {
      students{
         id
         firstName
         lastName
         college{
            name
         }
      }
   }`
   const {data} = await client.query({query}) ;
   return data.students;
}

Bạn chỉ cần giữ index.js trong srcthư mục và index.html trong thư mục chung; tất cả các tệp khác được tạo tự động có thể bị xóa.

Cấu trúc thư mục được đưa ra dưới đây:

hello-world-client /
   -->node_modules
   -->public
         index.html
   -->src
         index.js
   -->package.json

Sau đây là index.js trong ứng dụng phản ứng -

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

// apollo client

import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'

const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
   link: new HttpLink({uri:endPointUrl}),
   cache:new InMemoryCache()
});

async function loadStudentsAsync() {
   const query = gql`
   {
      students{
         id
         firstName
         lastName
         college{
            name
         }
      }
   }
   `
   const {data} = await client.query({query}) ;
   return data.students;
}
class  App  extends Component {
   constructor(props) {
      super(props);
      this.state = {
         students:[]
      }
      this.studentTemplate =  [];
   }
   async loadStudents() {
      const studentData =  await loadStudentsAsync();
      this.setState({
         students: studentData
      })
      console.log("loadStudents")
   }
   render() {
      return(
         <div>
            <input type = "button"  value = "loadStudents" onClick = {this.loadStudents.bind(this)}/>
            <div>
               <br/>
               <hr/>
               <table border = "3">
                  <thead>
                     <tr>
                        <td>First Name</td>
                        <td>Last Name</td>
                        <td>college Name</td>
                     </tr>
                  </thead>
                  
                  <tbody>
                     {
                        this.state.students.map(s => {
                           return (
                              <tr key = {s.id}>
                                 <td>
                                    {s.firstName}
                                 </td>
                                 <td>
                                    {s.lastName}
                                 </td>
                                 <td>
                                    {s.college.name}
                                 </td>
                              </tr>
                           )
                        })
                     }
                  </tbody>
               </table>
            </div>
         </div>
      )
   }
}
ReactDOM.render(<App/>, document.getElementById('root'));

Ứng dụng react sẽ tải sinh viên từ máy chủ GraphQL, sau khi chúng ta nhấp vào nút loadStudents như hình dưới đây -

Xác thực là quá trình hoặc hành động xác minh danh tính của người dùng hoặc một quá trình. Điều quan trọng là ứng dụng phải xác thực người dùng để đảm bảo rằng dữ liệu không có sẵn cho người dùng ẩn danh. Trong phần này, chúng ta sẽ học cách xác thực một máy khách GraphQL.

JWT Express

Trong ví dụ này, chúng tôi sẽ sử dụng jQuery để tạo một ứng dụng khách. Để xác thực yêu cầu, chúng tôi sẽ sử dụng express-jwt ở phía máy chủ.

Mô-đun express-jwt là một phần mềm trung gian cho phép bạn xác thực các yêu cầu HTTP bằng cách sử dụng mã thông báo JWT. Mã thông báo web JSON (JWT) là một chuỗi dài xác định người dùng đã đăng nhập.

Khi người dùng đăng nhập thành công, máy chủ sẽ tạo mã thông báo JWT. Mã thông báo này xác định rõ ràng một bản ghi. Nói cách khác, mã thông báo là đại diện cho danh tính của người dùng. Vì vậy, lần sau, khi khách hàng đến máy chủ, nó phải xuất trình mã thông báo này để nhận các tài nguyên cần thiết. Ứng dụng khách có thể là ứng dụng di động hoặc ứng dụng web.

Hình minh họa

Chúng ta sẽ làm theo một quy trình từng bước để hiểu được minh họa này.

Thiết lập máy chủ

Sau đây là các bước để thiết lập máy chủ -

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục auth-server-app. Thay đổi thư mục của bạn thành auth-server-app từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

schema.graphql auth-server-app
type Query
{
   greetingWithAuth:String
}

Bước 3 - Thêm trình phân giải

Tạo một tệp resolvers.js trong thư mục dự án và thêm mã sau:

Trình phân giải sẽ xác minh xem đối tượng người dùng được xác thực có sẵn trong đối tượng ngữ cảnh của GraphQL hay không. Nó sẽ đưa ra một ngoại lệ nếu người dùng đã xác thực không có sẵn.

const db = require('./db')

const Query = {
   greetingWithAuth:(root,args,context,info) => {

      //check if the context.user is null
      if (!context.user) {
         throw new Error('Unauthorized');
      }
      return "Hello from TutorialsPoint, welcome back : "+context.user.firstName;
   }
}

module.exports = {Query}

Bước 4 - Tạo tệp Server.js

Phần mềm trung gian xác thực xác thực người gọi bằng Mã thông báo web JSON. URL để xác thực là http://localhost:9000/login.

Đây là một hoạt động đăng bài. Người dùng phải gửi email và mật khẩu sẽ được xác thực từ chương trình phụ trợ. Nếu mã thông báo hợp lệ được tạo bằng phương thức jwt.sign, khách hàng sẽ phải gửi mã này trong tiêu đề cho các yêu cầu tiếp theo.

Nếu mã thông báo hợp lệ, req.user sẽ được đặt với đối tượng JSON được giải mã để được phần mềm trung gian sau này sử dụng để ủy quyền và kiểm soát truy cập.

Đoạn mã sau sử dụng hai mô-đun - jsonwebtoken và express-jwt để xác thực các yêu cầu -

  • Khi người dùng nhấp vào greet, một yêu cầu cho tuyến đường / graphql được đưa ra. Nếu người dùng không được xác thực, anh ta sẽ được nhắc tự xác thực.

  • Người dùng được hiển thị với một biểu mẫu chấp nhận id email và mật khẩu. Trong ví dụ của chúng tôi, / tuyến đường đăng nhập chịu trách nhiệm xác thực người dùng.

  • Tuyến / đăng nhập xác minh xem có tìm thấy khớp trong cơ sở dữ liệu cho thông tin xác thực do người dùng cung cấp hay không.

  • Nếu thông tin xác thực không hợp lệ, ngoại lệ HTTP 401 sẽ được trả lại cho người dùng.

  • Nếu thông tin xác thực hợp lệ, mã thông báo sẽ được máy chủ tạo. Mã thông báo này được gửi như một phần phản hồi cho người dùng. Điều này được thực hiện bởi hàm jwt.sign.

const expressJwt = require('express-jwt');
const jwt = require('jsonwebtoken');

//private key
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');

app.post('/login', (req, res) => {
   const {email, password} = req.body;
   
   //check database
   const user = db.students.list().find((user) =>  user.email === email);
   if (!(user && user.password === password)) {
      res.sendStatus(401);
      return;
   }
   
   //generate a token based on private key, token doesn't have an expiry
   const token = jwt.sign({sub: user.id}, jwtSecret);
   res.send({token});
});

Đối với mọi yêu cầu, hàm app.use () sẽ được gọi. Điều này lần lượt sẽ gọi phần mềm trung gian expressJWT. Phần mềm trung gian này sẽ giải mã Mã thông báo web JSON. Id người dùng được lưu trữ trong mã thông báo sẽ được truy xuất và lưu trữ dưới dạng người dùng thuộc tính trong đối tượng yêu cầu.

//decodes the JWT and stores in request object
app.use(expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
}));

Để cung cấp thuộc tính người dùng trong ngữ cảnh GraphQL, thuộc tính này được gán cho context đối tượng như hình dưới đây -

//Make req.user available to GraphQL context
app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user &&apm; db.students.get(req.user.sub)}
})));

Tạo nên server.js trong đường dẫn thư mục hiện tại. Tệp server.js hoàn chỉnh như sau:

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');

var port = process.env.PORT || 9000
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')

const schema = makeExecutableSchema({typeDefs, resolvers})

app.use(cors(), bodyParser.json(), expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
}));

const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')

app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user && db.students.get(req.user.sub)}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

//authenticate students
app.post('/login', (req, res) => {
   const email = req.body.email;
   const password = req.body.password;

   const user = db.students.list().find((user) =>  user.email === email);
   if (!(user && user.password === password)) {
      res.sendStatus(401);
      return;
   }
   const token = jwt.sign({sub: user.id}, jwtSecret);
   res.send({token});
});

app.listen(port, () => console.info(`Server started on port ${port}`));

Bước 5 - Chạy ứng dụng

Thực hiện lệnh  npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sử dụng GraphiQL làm máy khách để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   greetingWithAuth
}

Trong câu trả lời dưới đây, chúng tôi đã gặp lỗi vì chúng tôi không phải là người dùng được xác thực.

{
   "data": {
      "greetingWithAuth": null
   },
   "errors": [
      {
         "message": "Unauthorized",
         "locations": [
            {
               "line": 2,
               "column": 3
            }
         ],
         "path": [
            "greetingWithAuth"
         ]
      }
   ]
}

Trong phần tiếp theo, chúng ta hãy tạo một ứng dụng khách để xác thực.

Thiết lập ứng dụng khách JQuery

Trong ứng dụng khách, một nút chào được cung cấp sẽ gọi lược đồ greetingWithAuth. Nếu bạn nhấp vào nút mà không đăng nhập, nó sẽ cung cấp cho bạn thông báo lỗi như bên dưới:

Khi bạn đăng nhập với người dùng có sẵn trong cơ sở dữ liệu, màn hình sau sẽ xuất hiện:

Truy cập vào greeting, trước tiên chúng ta cần truy cập vào URL http://localhost:9000/login lộ trình như bên dưới.

Phản hồi sẽ chứa mã thông báo được tạo từ máy chủ.

$.ajax({
   url:"http://localhost:9000/login",
   contentType:"application/json",
   type:"POST",
   data:JSON.stringify({email,password}),
   success:function(response) {
      loginToken = response.token;
      $('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
   },
   error:(xhr,err) =>  alert('error')
})

Sau khi đăng nhập thành công, chúng ta có thể truy cập vào greetingWithAuth schema như đưa ra dưới đây. Cần phải có Người cấp quyền cho tất cả các yêu cầu tiếp theo với mã thông báo mang.

{ 
   url: "http://localhost:9000/graphql",
   contentType: "application/json",
   headers: {"Authorization": 'bearer '+loginToken},  type:'POST',
   data: JSON.stringify({
   query:`{greetingWithAuth}`
}

Sau đây là mã cho index.html -

<!DOCTYPE html>
<html>
   <head>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script>
         $(document).ready(function() { let loginToken = ""; $("#btnGreet").click(function() {
                  $.ajax({url: "http://localhost:9000/graphql", contentType: "application/json", headers: {"Authorization": 'bearer '+loginToken}, type:'POST', data: JSON.stringify({ query:`{greetingWithAuth}` }), success: function(result) { $("#greetingDiv").html("<h1>"+result.data.greetingWithAuth+"</h1>")
                  },
                  error:function(jQxhr,error) {
                     if(jQxhr.status == 401) {
                        $("#greetingDiv").html('please authenticate first!!') .css({"color":"red",'font-weight':'bold'}) return; } $("#greetingDiv").html('error').css("color","red");
                  }
               });
            });
            $('#btnAuthenticate').click(function() { var email = $("#txtEmail").val();
               var password =  $("#txtPwd").val(); if(email && password) { $.ajax({
                     url:"http://localhost:9000/login",
                     contentType:"application/json",
                     type:"POST",
                     data:JSON.stringify({email,password}),
                     success:function(response) {
                        loginToken =  response.token;
                        $('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
                     },
                     error:(xhr,err) =>  alert('error')
                  })
               }else alert("email and pwd empty")
            })
         });
      </script>
   </head>
   
   <body>
      <h1> GraphQL Authentication </h1>
      <hr/>
      <section>
         <button id = "btnGreet">Greet</button>
         <br/> <br/>
         <div id = "greetingDiv"></div>
      </section>
      <br/> <br/> <br/>
      <hr/>
      
      <section id = "LoginSection">
         <header>
            <h2>*Login first to  access greeting </h2>
         </header>
         <input type = "text" value = "[email protected]" placeholder = "enter email" id = "txtEmail"/>
         <br/>
         
         <input type = "password" value = "pass123" placeholder = "enter password" id = "txtPwd"/>
         <br/>
         
         <input type = "button" id = "btnAuthenticate"  value = "Login"/>
         <p id = "authStatus"></p>
      </section>
   </body>
</html>

Bộ nhớ đệm là quá trình lưu trữ dữ liệu trong một vùng lưu trữ tạm thời được gọi là cache. Khi bạn quay lại trang mà bạn đã truy cập gần đây, trình duyệt có thể lấy các tệp đó từ bộ nhớ cache thay vì máy chủ ban đầu. Điều này tiết kiệm thời gian của bạn và mạng khỏi gánh nặng của lưu lượng bổ sung.

Các ứng dụng khách tương tác với GraphQL chịu trách nhiệm lưu dữ liệu vào bộ nhớ đệm ở cuối của chúng. Một mô hình khả thi cho điều này là dành một trường, như id, để làm mã định danh duy nhất trên toàn cầu.

InMemory Cache

InMemoryCache là một kho lưu trữ dữ liệu chuẩn hóa thường được sử dụng trong các ứng dụng khách GraphQL mà không cần sử dụng thư viện khác như Redux.

Mã mẫu để sử dụng InMemoryCache với ApolloClient được đưa ra dưới đây:

import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();

const client = new ApolloClient({
   link: new HttpLink(),
   cache
});

Hàm tạo InMemoryCache nhận một đối tượng cấu hình tùy chọn với các thuộc tính để tùy chỉnh bộ nhớ cache của bạn.

Sr.No. Mô tả về Thông Số
1

addTypename

Một boolean để xác định xem có thêm __typename vào tài liệu hay không (mặc định: true)

2

dataIdFromObject

Một hàm nhận một đối tượng dữ liệu và trả về một mã định danh duy nhất được sử dụng khi chuẩn hóa dữ liệu trong cửa hàng

3

fragmentMatcher

Theo mặc định, InMemoryCache sử dụng trình so khớp phân đoạn heuristic

4

cacheRedirects

Bản đồ các chức năng để chuyển hướng một truy vấn đến một mục nhập khác trong bộ đệm trước khi một yêu cầu diễn ra.

Hình minh họa

Chúng tôi sẽ tạo một ứng dụng trang đơn trong ReactJS với hai tab - một cho tab trang chủ và một cho sinh viên. Tab sinh viên sẽ tải dữ liệu từ API máy chủ GraphQL. Ứng dụng sẽ truy vấn dữ liệu sinh viên khi người dùng điều hướng từ tab trang chủ đến tab sinh viên. Dữ liệu kết quả sẽ được ứng dụng lưu vào bộ nhớ đệm.

Chúng tôi cũng sẽ truy vấn thời gian sử dụng máy chủ getTimetrường để xác minh xem trang có được lưu vào bộ nhớ đệm hay không. Nếu dữ liệu được trả về từ bộ nhớ cache, trang sẽ hiển thị thời điểm yêu cầu đầu tiên được gửi đến máy chủ. Nếu dữ liệu là kết quả của một yêu cầu mới được gửi tới máy chủ, nó sẽ luôn hiển thị thời gian mới nhất từ ​​máy chủ.

Thiết lập máy chủ

Sau đây là các bước để thiết lập máy chủ -

Bước 1 - Tải xuống và cài đặt các phụ thuộc cần thiết cho dự án

Tạo một thư mục cache-server-app. Thay đổi thư mục của bạn thành cache-server-app từ thiết bị đầu cuối. Làm theo các bước từ 3 đến 5 được giải thích trong chương Thiết lập Môi trường.

Bước 2 - Tạo một lược đồ

Thêm vào schema.graphql tập tin trong thư mục dự án cache-server-app và thêm mã sau -

type Query {
   students:[Student]
   getTime:String
}

type Student {
   id:ID!
   firstName:String
   lastName:String
   fullName:String
}

Bước 3 - Thêm trình phân giải

Tạo một tệp giải quyết tệp tin.js trong thư mục dự án và thêm mã sau:

const db = require('./db')

const Query = {
      students:() => db.students.list(),
      getTime:() => {
      const today = new Date();
      var h = today.getHours();
      var m = today.getMinutes();
      var s = today.getSeconds();
      return `${h}:${m}:${s}`;
   }
}
module.exports = {Query}

Bước 4 - Chạy ứng dụng

Tạo tệp server.js. Tham khảo bước 8 trong Chương Thiết lập Môi trường. Thực hiện lệnh npm start trong terminal. Máy chủ sẽ hoạt động trên cổng 9000. Ở đây, chúng tôi sẽ sử dụng GraphiQL làm client để kiểm tra ứng dụng.

Mở trình duyệt và nhập URL http://localhost:9000/graphiql. Nhập truy vấn sau vào trình chỉnh sửa -

{
   getTime
   students {
      id
      firstName
   }
}

Câu trả lời mẫu hiển thị tên sinh viên và thời gian máy chủ.

{
   "data": {
      "getTime": "22:18:42",
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim"
         },
         {
            "id": "S1002",
            "firstName": "Kannan"
         },
         {
            "id": "S1003",
            "firstName": "Kiran"
         }
      ]
   }
}

Thiết lập ứng dụng khách ReactJS

Mở một thiết bị đầu cuối mới cho khách hàng. Thiết bị đầu cuối của máy chủ phải được duy trì chạy trước khi thực thi ứng dụng khách. Ứng dụng React sẽ chạy trên cổng số 3000 và ứng dụng máy chủ trên cổng số 9000.

Bước 1 - Tạo ứng dụng React

Trong thiết bị đầu cuối của máy khách, nhập lệnh sau:

npx create-react-app hello-world-client

Điều này sẽ cài đặt mọi thứ cần thiết cho một ứng dụng phản ứng điển hình. Cácnpx utilitycreate-react-appcông cụ tạo một dự án với tên hello-world-client. Sau khi cài đặt xong, hãy mở dự án trong VSCode.

Cài đặt mô-đun bộ định tuyến để phản ứng bằng lệnh sau: npm install react-router-dom.

Bước 2 - Bắt đầu hello-world-client

Thay đổi đường dẫn thư mục hiện tại trong terminal thành hello-world-client. Nhập npm start để khởi chạy dự án. Thao tác này sẽ chạy một máy chủ phát triển ở cổng 3000 và sẽ tự động mở trình duyệt và tải trang chỉ mục.

Điều này được hiển thị trong ảnh chụp màn hình dưới đây -

Bước 3 - Cài đặt thư viện khách hàng Apollo

Để cài đặt Ứng dụng khách Apollo, hãy mở một thiết bị đầu cuối mới và ở trong đường dẫn thư mục dự án hiện tại. Gõ lệnh sau:

npm install apollo-boost graphql

Thao tác này sẽ tải xuống các thư viện graphql cho phía máy khách và cả gói Apollo Boost. Chúng tôi có thể xác minh chéo điều này bằng cách nhập các phụ thuộc vào apollo-boost npm view. Điều này sẽ có nhiều phụ thuộc như hình dưới đây -

{ 
   'apollo-cache': '^1.1.15',
   'apollo-cache-inmemory': '^1.2.8',
   'apollo-client': '^2.4.0',
   'apollo-link': '^1.0.6',
   'apollo-link-error': '^1.0.3',
   'apollo-link-http': '^1.3.1',
   'apollo-link-state': '^0.4.0',
   'graphql-tag': '^2.4.2' 
}

Chúng ta có thể thấy rõ rằng thư viện apollo-client đã được cài đặt.

Bước 4 - Sửa đổi thành phần ứng dụng trong tệp index.js

Đối với một ứng dụng phản ứng đơn giản, bạn chỉ cần giữ index.js trong src thư mục và index.htmltrong thư mục chung; tất cả các tệp khác được tạo tự động có thể bị xóa.

Cấu trúc thư mục được đưa ra dưới đây:

hello-world-client /
   -->node_modules
   -->public
      index.html
   -->src
      index.js
      students.js
   -->package.json

Thêm một tệp bổ sung student.js sẽ chứa Thành phần Sinh viên. Thông tin chi tiết về sinh viên được tìm nạp thông qua Thành phần Sinh viên. Trong Thành phần ứng dụng, chúng tôi đang sử dụng HashRouter.

Sau đây là index.js trong ứng dụng phản ứng -

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {HashRouter, Route, Link} from 'react-router-dom'

//components
import Students from './students'
class App extends Component {
   render() {
      return(
         <div><h1>Home !!</h1>
         <h2>Welcome to React Application !! </h2>
         </div>
      )
   }
}

function getTime() {
   var d = new Date();
   return d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()
}

const routes = <HashRouter>
   <div>
      <h4>Time from react app:{getTime()}</h4>
      <header>
         <h1>  <Link to="/">Home</Link> 
         <Link to = "/students">Students</Link>  </h1>
      </header>
      <Route exact path = "/students" component = {Students}></Route>
      <Route exact path = "/" component = {App}></Route>
   </div>
</HashRouter>

ReactDOM.render(routes, document.querySelector("#root"))

Bước 5 - Chỉnh sửa học sinh thành phần trong Students.js

Trong Hợp phần Sinh viên, chúng tôi sẽ sử dụng hai cách tiếp cận sau để tải dữ liệu:

  • Fetch API (loadStudents_noCache) - Điều này sẽ kích hoạt một yêu cầu mới mỗi khi nhấp vào tab sinh viên.

  • Apollo Client (loadWithApolloclient) - Thao tác này sẽ lấy dữ liệu từ bộ nhớ đệm.

Thêm một chức năng loadWithApolloclienttruy vấn nào cho sinh viên và thời gian từ máy chủ. Chức năng này sẽ kích hoạt bộ nhớ đệm. Ở đây chúng tôi sử dụng một hàm gql để phân tích cú pháp truy vấn.

async loadWithApolloclient() {
   const query = gql`{
      getTime
      students {
         id
         firstName
      }
   }`;

   const {data} = await  client.query({query})
   return data;
}

Các Fetch APIlà một giao diện đơn giản để tìm nạp tài nguyên. Tìm nạp giúp dễ dàng thực hiện các yêu cầu web và xử lý phản hồi hơn so với XMLHttpRequest cũ hơn. Phương thức sau cho thấy việc tải dữ liệu trực tiếp bằng api tìm nạp:

async  loadStudents_noCache() {
      const response = await fetch('http://localhost:9000/graphql', {
      method:'POST',
      headers:{'content-type':'application/json'},
      body:JSON.stringify({query:`{
         getTime
         students {
            id
            firstName
         }
      }`})
   })

   const rsponseBody = await response.json();
   return rsponseBody.data;
}

Trong hàm tạo của StudentsComponent, hãy gọi loadWithApolloClientphương pháp. Hoàn chỉnh Student.js tệp bên dưới -

import React, {Component} from 'react';
import { Link} from 'react-router-dom'

//Apollo Client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const client = new ApolloClient({
   link: new HttpLink({uri:`http://localhost:9000/graphql`}),
   cache:new InMemoryCache()
})

class Students extends Component {
   constructor(props) {
      super(props);
      this.state = {
         students:[{id:1,firstName:'test'}],
         serverTime:''
      }
      this.loadWithApolloclient().then(data => {
         this.setState({
            students:data.students,
            serverTime:data.getTime
         })
      })
   }
   
   async  loadStudents_noCache() {
      const response = await fetch('http://localhost:9000/graphql', {
         method:'POST',
         headers:{'content-type':'application/json'},
         body:JSON.stringify({query:`{
            getTime
            students {
               id
               firstName
            }
         }`})
      })
      const rsponseBody =  await response.json();
      return rsponseBody.data;
   }
   
   async loadWithApolloclient() {
      console.log("inside apollo client function")
      const query = gql`{
         getTime
         students {
            id
            firstName
         }
      }`;
      const {data} = await  client.query({query})
      return data;
   }
   
   render() {
      return(
         <div>
            <h3>Time from GraphQL server :{this.state.serverTime}</h3>
            <p>Following Students Found </p>
            <div>
               <ul>
                  {
                     this.state.students.map(s => {
                        return(
                           <li key = {s.id}>
                              {s.firstName}
                           </li>
                        )
                     })
                  }
               </ul>
            </div>
         </div>
      )
   }
}
export default Students

Bước 6 - Chạy ứng dụng React với npm start

Bạn có thể kiểm tra ứng dụng phản ứng bằng cách chuyển từ tab trang chủ sang tab sinh viên. Sau khi tab sinh viên được tải với dữ liệu từ máy chủ. Nó sẽ lưu dữ liệu vào bộ nhớ cache. Bạn có thể kiểm tra nó bằng cách chuyển từ tab nhà sang tab sinh viên nhiều lần. Đầu ra sẽ như hình dưới đây -

Nếu bạn đã tải trang sinh viên đầu tiên bằng cách nhập URL, http://localhost:3000/#/students, bạn có thể thấy rằng thời gian tải cho ứng dụng phản ứng và GraphQL sẽ gần giống nhau. Sau đó, nếu bạn chuyển sang chế độ xem chính và quay lại máy chủ GraphQL, thời gian sẽ không thay đổi. Điều này cho thấy dữ liệu được lưu trong bộ nhớ cache.

Bước 7 - Thay đổi cuộc gọi loadWithApolloclient thành loadStudents_noCache

Nếu bạn thay đổi phương thức tải thành loadStudents_noCachetrong hàm tạo của StudentComponent, đầu ra sẽ không lưu dữ liệu vào bộ nhớ cache. Điều này cho thấy sự khác biệt giữa bộ nhớ đệm và không bộ nhớ đệm.

this.loadStudents_noCache().then(data => {
   this.setState({
      students:data.students,
      serverTime:data.getTime
   })
})

Từ kết quả trên, rõ ràng là nếu bạn chuyển đổi qua lại giữa các tab, thời gian từ máy chủ graphql sẽ luôn là muộn nhất có nghĩa là dữ liệu không được lưu trong bộ nhớ cache.