GraphQL - คู่มือฉบับย่อ

GraphQL เป็นเทคโนโลยีฝั่งเซิร์ฟเวอร์แบบโอเพ่นซอร์สซึ่งพัฒนาโดย Facebook เพื่อเพิ่มประสิทธิภาพการเรียก RESTful API เป็นเครื่องมือดำเนินการและภาษาแบบสอบถามข้อมูล ในบทนี้เราจะพูดถึงข้อดีของการใช้ GraphQL

ทำไมต้อง GraphQL

RESTful API เป็นไปตามแนวทางที่มุ่งเน้นทรัพยากรที่ชัดเจนและมีโครงสร้างที่ดี อย่างไรก็ตามเมื่อข้อมูลมีความซับซ้อนมากขึ้นเส้นทางก็จะยาวขึ้น บางครั้งไม่สามารถดึงข้อมูลด้วยคำขอเดียวได้ นี่คือจุดที่ GraphQL มีประโยชน์ GraphQL จัดโครงสร้างข้อมูลในรูปแบบของกราฟด้วยไวยากรณ์การสืบค้นที่มีประสิทธิภาพสำหรับการข้ามผ่านการเรียกค้นและการแก้ไขข้อมูล

ต่อไปนี้เป็นข้อดีของการใช้ GraphQL query Language -

ขอสิ่งที่คุณต้องการ - และรับมัน

ส่งแบบสอบถาม GraphQL ไปยัง API ของคุณและรับสิ่งที่คุณต้องการ การสืบค้น GraphQL จะแสดงผลลัพธ์ที่คาดเดาได้เสมอ แอปพลิเคชันที่ใช้ GraphQL มีความรวดเร็วและเสถียร ซึ่งแตกต่างจากบริการ Restful แอปพลิเคชันเหล่านี้สามารถ จำกัด ข้อมูลที่ควรดึงมาจากเซิร์ฟเวอร์

ตัวอย่างต่อไปนี้จะช่วยให้คุณเข้าใจสิ่งนี้ได้ดีขึ้น -

ขอให้เราพิจารณาวัตถุธุรกิจนักศึกษามีคุณลักษณะid, ชื่อ, นามสกุลและcollegeName สมมติว่าความต้องการใช้โทรศัพท์มือถือสามารถดึงข้อมูลเพียงfirstNameและรหัส ถ้าเราออกแบบจุดสิ้นสุด REST เช่น/ api / v1 / studentsมันจะจบลงด้วยการดึงข้อมูลสำหรับฟิลด์ทั้งหมดสำหรับอ็อบเจ็กต์นักเรียน ซึ่งหมายความว่าข้อมูลถูกดึงมาโดยบริการ RESTful มากเกินไป ปัญหานี้สามารถแก้ไขได้โดยใช้ GraphQL

พิจารณาแบบสอบถาม GraphQL ที่ระบุด้านล่าง -

{
   students {
      id
      firstName
   }
}

สิ่งนี้จะส่งคืนค่าสำหรับฟิลด์ id และ firstname เท่านั้น แบบสอบถามจะไม่ดึงค่าสำหรับแอตทริบิวต์อื่น ๆ ของวัตถุนักเรียน การตอบสนองของข้อความค้นหาที่แสดงด้านบนเป็นดังที่แสดงด้านล่าง -

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

รับทรัพยากรมากมายในคำขอเดียว

การสืบค้น GraphQL ช่วยให้ดึงข้อมูลทางธุรกิจที่เกี่ยวข้องได้อย่างราบรื่นในขณะที่ REST API ทั่วไปต้องการการโหลดจาก URL หลายรายการ GraphQL API จะดึงข้อมูลทั้งหมดที่แอปพลิเคชันของคุณต้องการในคำขอเดียว แอปพลิเคชันที่ใช้ GraphQL สามารถทำงานได้อย่างรวดเร็วแม้ในการเชื่อมต่อเครือข่ายมือถือที่ช้า

ให้เราพิจารณาอีกหนึ่งวัตถุทางธุรกิจวิทยาลัยซึ่งมีคุณลักษณะ: ชื่อและที่ตั้ง นักศึกษาวัตถุธุรกิจมีความสัมพันธ์เชื่อมโยงกับวัตถุวิทยาลัย ถ้าเราจะใช้ REST API เพื่อดึงข้อมูลรายละเอียดของนักเรียนและวิทยาลัยของพวกเขาเราจะสิ้นสุดการทำสองหน้าไปยังเซิร์ฟเวอร์เช่น/ API / v1 / นักศึกษาและ/ API / v1 / วิทยาลัย ซึ่งจะนำไปสู่การดึงข้อมูลในแต่ละคำขอ ดังนั้นแอปพลิเคชันมือถือจึงถูกบังคับให้โทรไปยังเซิร์ฟเวอร์หลายครั้งเพื่อรับข้อมูลที่ต้องการ

อย่างไรก็ตามแอปพลิเคชันมือถือสามารถดึงรายละเอียดของวัตถุทั้งนักศึกษาและวิทยาลัยได้ในคำขอเดียวโดยใช้ GraphQL

ต่อไปนี้เป็นแบบสอบถาม GraphQL เพื่อดึงข้อมูล -

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

ผลลัพธ์ของข้อความค้นหาข้างต้นประกอบด้วยฟิลด์ที่เราร้องขอตามที่แสดงด้านล่าง -

{
   "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"
            }
         }
      ]
   }
}

อธิบายสิ่งที่เป็นไปได้ด้วยระบบประเภท

GraphQL ถูกพิมพ์อย่างมากและการสืบค้นจะขึ้นอยู่กับฟิลด์และประเภทข้อมูลที่เกี่ยวข้อง หากมีประเภทไม่ตรงกันในแบบสอบถาม GraphQL แอปพลิเคชันเซิร์ฟเวอร์จะแสดงข้อความแสดงข้อผิดพลาดที่ชัดเจนและเป็นประโยชน์ สิ่งนี้ช่วยในการดีบักที่ราบรื่นและการตรวจหาจุดบกพร่องโดยแอปพลิเคชันไคลเอ็นต์ได้ง่าย GraphQL ยังมีไลบรารีฝั่งไคลเอ็นต์ที่สามารถช่วยลดการแปลงและการแยกวิเคราะห์ข้อมูลที่ชัดเจน

ตัวอย่างประเภทข้อมูลนักศึกษาและวิทยาลัยมีให้ด้านล่าง -

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]
}

เคลื่อนที่ได้เร็วขึ้นด้วยเครื่องมือสำหรับนักพัฒนาที่มีประสิทธิภาพ

GraphQL มีเครื่องมือสำหรับนักพัฒนามากมายสำหรับการจัดทำเอกสารและการทดสอบแบบสอบถาม GraphiQL เป็นเครื่องมือที่ยอดเยี่ยมที่สร้างเอกสารของแบบสอบถามและสคีมา นอกจากนี้ยังมีเครื่องมือแก้ไขแบบสอบถามเพื่อทดสอบ GraphQL API และความสามารถในการเติมโค้ดอัจฉริยะในขณะที่สร้างแบบสอบถาม

ในบทนี้เราจะเรียนรู้เกี่ยวกับการตั้งค่าสภาพแวดล้อมสำหรับ GraphQL ในการดำเนินการตามตัวอย่างในบทช่วยสอนนี้คุณจะต้องมีสิ่งต่อไปนี้ -

  • คอมพิวเตอร์ที่ใช้ Linux, macOS หรือ Windows

  • เว็บเบราว์เซอร์ควรเป็น Google Chrome เวอร์ชันล่าสุด

  • ติดตั้ง Node.js เวอร์ชันล่าสุดแล้ว ขอแนะนำให้ใช้ LTS เวอร์ชันล่าสุด

  • Visual Studio Code ที่มีนามสกุล GraphQL สำหรับ VSCode ที่ติดตั้งหรือโปรแกรมแก้ไขโค้ดที่คุณเลือก

วิธีสร้างเซิร์ฟเวอร์ GraphQL ด้วย Nodejs

เราจะดำเนินการตามขั้นตอนอย่างละเอียดเพื่อสร้างเซิร์ฟเวอร์ GraphQL ด้วย Nodejs ดังที่แสดงด้านล่าง -

ขั้นตอนที่ 1 - ตรวจสอบเวอร์ชันโหนดและ Npm

หลังจากติดตั้ง NodeJs ให้ตรวจสอบเวอร์ชันของโหนดและ npm โดยใช้คำสั่งต่อไปนี้บนเทอร์มินัล -

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

C:\Users\Admin>npm -v
5.6.0

ขั้นตอนที่ 2 - สร้างโฟลเดอร์โครงการและเปิดใน VSCode

โฟลเดอร์รูทของโปรเจ็กต์สามารถตั้งชื่อเป็นแอพทดสอบ

เปิดโฟลเดอร์โดยใช้โปรแกรมแก้ไขโค้ด Visual Studio โดยใช้คำแนะนำด้านล่าง -

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

ขั้นตอนที่ 3 - สร้าง package.json และติดตั้งการอ้างอิง

สร้างไฟล์ package.json ซึ่งจะมีการอ้างอิงทั้งหมดของแอปพลิเคชันเซิร์ฟเวอร์ 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:\Users\Admin\test-app>npm install

ขั้นตอนที่ 4 - สร้างฐานข้อมูลไฟล์แบบแบนในโฟลเดอร์ข้อมูล

ในขั้นตอนนี้เราใช้ไฟล์แบบแบนเพื่อจัดเก็บและดึงข้อมูล สร้างข้อมูลโฟลเดอร์และเพิ่มสองไฟล์students.json และ colleges.json.

ต่อไปนี้คือไฟล์ colleges.json ไฟล์ -

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

ต่อไปนี้คือไฟล์ students.json ไฟล์ -

[
   {
      "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"
   }
]

ขั้นตอนที่ 5 - สร้างชั้นการเข้าถึงข้อมูล

เราจำเป็นต้องสร้างที่เก็บข้อมูลที่โหลดเนื้อหาโฟลเดอร์ข้อมูล ในกรณีนี้เราต้องตัวแปรคอลเลกชัน, นักเรียนและวิทยาลัย เมื่อใดก็ตามที่แอปพลิเคชันต้องการข้อมูลก็จะใช้ตัวแปรการรวบรวมเหล่านี้

สร้างไฟล์ db.js ในโฟลเดอร์โปรเจ็กต์ดังนี้ -

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

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

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

ขั้นตอนที่ 6 - สร้างไฟล์ Schema, schema.graphql

สร้างไฟล์สคีมาในโฟลเดอร์โครงการปัจจุบันและเพิ่มเนื้อหาต่อไปนี้ -

type Query  {
   test: String
}

ขั้นตอนที่ 7 - สร้างไฟล์ Resolver, resolvers.js

สร้างไฟล์ตัวแก้ไขในโฟลเดอร์โครงการปัจจุบันและเพิ่มเนื้อหาต่อไปนี้ -

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

ขั้นตอนที่ 8 - สร้าง Server.js และกำหนดค่า GraphQL

สร้างไฟล์เซิร์ฟเวอร์และกำหนดค่า GraphQL ดังนี้ -

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}`
   )
);

ขั้นตอนที่ 9 - เรียกใช้แอปพลิเคชันและทดสอบกับ GraphiQL

ตรวจสอบโครงสร้างโฟลเดอร์ของแอปทดสอบโครงการดังนี้ -

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

รันคำสั่ง npm start ตามที่ระบุด้านล่าง -

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

เซิร์ฟเวอร์กำลังทำงานในพอร์ต 9000 ดังนั้นเราจึงสามารถทดสอบแอปพลิเคชันโดยใช้เครื่องมือ GraphiQL เปิดเบราว์เซอร์และป้อน URL http: // localhost: 9000 / graphiql พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   Test 
}

การตอบสนองจากเซิร์ฟเวอร์ได้รับด้านล่าง -

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

GraphQL เป็นข้อกำหนดที่อธิบายลักษณะการทำงานของเซิร์ฟเวอร์ GraphQL เป็นชุดของแนวทางในการจัดการคำขอและการตอบสนองเช่นโปรโตคอลที่รองรับรูปแบบของข้อมูลที่เซิร์ฟเวอร์ยอมรับได้รูปแบบของการตอบกลับที่เซิร์ฟเวอร์ส่งคืนเป็นต้นคำขอที่ไคลเอ็นต์ส่งไปยัง GraphQL เซิร์ฟเวอร์เรียกว่าแบบสอบถาม แนวคิดที่สำคัญอีกประการหนึ่งของ GraphQL คือ agnostics ชั้นการขนส่ง สามารถใช้กับโปรโตคอลเครือข่ายที่มีเช่น TCP, websocket หรือโปรโตคอลชั้นการขนส่งอื่น ๆ นอกจากนี้ยังเป็นกลางกับฐานข้อมูลดังนั้นคุณสามารถใช้กับฐานข้อมูลเชิงสัมพันธ์หรือฐานข้อมูล NoSQL ได้

GraphQL Server สามารถใช้งานได้โดยใช้วิธีใดก็ได้จากสามวิธีด้านล่าง -

  • เซิร์ฟเวอร์ GraphQL พร้อมฐานข้อมูลที่เชื่อมต่อ
  • เซิร์ฟเวอร์ GraphQL ที่รวมระบบที่มีอยู่
  • แนวทางไฮบริด

เซิร์ฟเวอร์ GraphQL พร้อมฐานข้อมูลที่เชื่อมต่อ

สถาปัตยกรรมนี้มีเซิร์ฟเวอร์ GraphQL ที่มีฐานข้อมูลในตัวและมักใช้กับโครงการใหม่ ๆ ในการรับแบบสอบถามเซิร์ฟเวอร์จะอ่านเพย์โหลดของคำขอและดึงข้อมูลจากฐานข้อมูล ซึ่งเรียกว่าการแก้ไขแบบสอบถาม การตอบกลับไปยังไคลเอนต์เป็นไปตามรูปแบบที่ระบุไว้ในข้อกำหนด GraphQL อย่างเป็นทางการ

ในแผนภาพด้านบนเซิร์ฟเวอร์ GraphQL และฐานข้อมูลจะรวมอยู่ในโหนดเดียว ไคลเอนต์ (เดสก์ท็อป / มือถือ) สื่อสารกับเซิร์ฟเวอร์ GraphQL ผ่าน HTTP เซิร์ฟเวอร์ประมวลผลคำขอดึงข้อมูลจากฐานข้อมูลและส่งกลับไปยังไคลเอนต์

เซิร์ฟเวอร์ GraphQL รวมระบบที่มีอยู่

แนวทางนี้มีประโยชน์สำหรับ บริษัท ที่มีโครงสร้างพื้นฐานเดิมและ API ที่แตกต่างกัน GraphQL สามารถใช้เพื่อรวมไมโครเซอร์วิสโครงสร้างพื้นฐานเดิมและ API ของบุคคลที่สามในระบบที่มีอยู่

ในแผนภาพด้านบน GraphQL API ทำหน้าที่เป็นส่วนต่อประสานระหว่างไคลเอนต์และระบบที่มีอยู่ แอปพลิเคชันไคลเอ็นต์สื่อสารกับเซิร์ฟเวอร์ GraphQL ซึ่งจะแก้ไขแบบสอบถาม

แนวทางแบบผสมผสาน

ในที่สุดเราสามารถรวมสองวิธีข้างต้นและสร้างเซิร์ฟเวอร์ GraphQL ในสถาปัตยกรรมนี้เซิร์ฟเวอร์ GraphQL จะแก้ไขคำขอใด ๆ ที่ได้รับ มันจะดึงข้อมูลจากฐานข้อมูลที่เชื่อมต่อหรือจาก API รวม สิ่งนี้แสดงในรูปด้านล่าง -

บทนี้จะกล่าวถึงส่วนประกอบ GraphQL ที่แตกต่างกันและวิธีที่พวกเขาสื่อสารกัน ส่วนประกอบแอปพลิเคชันทั้งหมดสามารถแยกแยะได้ดังนี้ -

  • ส่วนประกอบฝั่งเซิร์ฟเวอร์
  • ส่วนประกอบฝั่งไคลเอ็นต์

ส่วนประกอบฝั่งเซิร์ฟเวอร์

เซิร์ฟเวอร์ GraphQL สร้างองค์ประกอบหลักที่ฝั่งเซิร์ฟเวอร์และอนุญาตให้แยกวิเคราะห์คำค้นหาที่มาจากแอปพลิเคชันไคลเอนต์ GraphQL Apollo Server เป็นที่นิยมใช้มากที่สุดในการนำข้อกำหนด GraphQL ส่วนประกอบการเขียนโปรแกรมเซิร์ฟเวอร์อื่น ๆ มีดังต่อไปนี้ -

ซีเนียร์ สิ่งจำเป็นและคำอธิบายของเซิร์ฟเวอร์
1

Schema

สคีมา GraphQL เป็นศูนย์กลางของการใช้งานเซิร์ฟเวอร์ GraphQL และอธิบายถึงฟังก์ชันการทำงานที่มีให้สำหรับไคลเอนต์ที่เชื่อมต่อ

2

Query

แบบสอบถาม GraphQL คือคำขอแอปพลิเคชันไคลเอนต์เพื่อดึงข้อมูลจากฐานข้อมูลหรือ API เดิม

3

Resolver

Resolvers ให้คำแนะนำในการเปลี่ยนการดำเนินการ GraphQL ให้เป็นข้อมูล พวกเขาแก้ไขแบบสอบถามเป็นข้อมูลโดยการกำหนดฟังก์ชันตัวแก้ไข

ส่วนประกอบฝั่งไคลเอ็นต์

ด้านล่างนี้เป็นส่วนประกอบฝั่งไคลเอ็นต์ -

ซีเนียร์ เครื่องมือและคำอธิบาย
1

GraphiQL

อินเทอร์เฟซที่ใช้เบราว์เซอร์สำหรับการแก้ไขและทดสอบการสืบค้นและการกลายพันธุ์ของ GraphQL

2

ApolloClient

เครื่องมือที่ดีที่สุดในการสร้างแอปพลิเคชันไคลเอนต์ GraphQL ทำงานร่วมกันได้ดีกับส่วนหน้าของ Javascript ทั้งหมด

แผนภาพด้านล่างแสดงไฟล์ Client-Server architecture. เว็บเซิร์ฟเวอร์สร้างขึ้นบน NodeJs และ Express framework มีการร้องขอไปยังเซิร์ฟเวอร์ Apollo GraphQL โดยแอปพลิเคชัน ReactJS (สร้างโดยใช้ไลบรารี Apollo Client) หรือแอปพลิเคชันเบราว์เซอร์ GraphiQL แบบสอบถามจะถูกแยกวิเคราะห์และตรวจสอบความถูกต้องตามสคีมาที่กำหนดไว้ในเซิร์ฟเวอร์ หากสคีมาของคำขอผ่านการตรวจสอบความถูกต้องฟังก์ชันตัวแก้ไขที่เกี่ยวข้องจะถูกดำเนินการ ตัวแก้ไขจะมีรหัสสำหรับดึงข้อมูลจาก API หรือฐานข้อมูล

ในบทนี้เราจะสร้าง API ง่ายๆที่ส่งคืนข้อความทักทาย HelloWorld และเข้าถึงโดยใช้ GraphiQL

ตัวอย่าง

ตัวอย่างนี้อ้างอิงจากเซิร์ฟเวอร์ NodeJS, Express และ Apollo เราจะเรียนรู้ที่จะรวบรวมแนวคิดทั้งหมดพร้อมกับขั้นตอนต่อไปนี้ -

ขั้นตอนที่ 1 - การตั้งค่า Express

ExpressJS เป็นกรอบงานเว็บแอปพลิเคชันที่ช่วยในการสร้างเว็บไซต์และเว็บแอปพลิเคชัน ในตัวอย่างนี้เราจะสร้าง GraphQL API ที่ด้านบนของเฟรมเวิร์ก Express

ขั้นตอนต่อไปคือการสร้างโฟลเดอร์ hello-world-serverและไปที่โฟลเดอร์เดียวกันจากเทอร์มินัล เพิ่ม package.json และตั้งชื่อให้กับแพ็กเกจ เนื่องจากแพ็คเกจนี้ใช้เป็นการภายในเท่านั้นเราจึงประกาศให้เป็นส่วนตัวได้

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

ติดตั้งการอ้างอิงสำหรับเซิร์ฟเวอร์ Express ดังที่แสดงด้านล่าง -

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

body-parserเป็นแพ็กเกจมิดเดิลแวร์ที่ช่วยให้ Express จัดการคำขอ HTTP Post ได้อย่างมีประสิทธิภาพ corsเป็นแพ็คเกจมิดเดิลแวร์อื่นที่จัดการการแชร์ทรัพยากรข้ามแหล่งที่มา

สร้างไฟล์ server.js ไฟล์ภายในโฟลเดอร์โครงการและพิมพ์สิ่งต่อไปนี้ -

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}`)

ในการตรวจสอบว่าเซิร์ฟเวอร์ Express ทำงานอยู่หรือไม่ให้รันโค้ดต่อไปนี้ในหน้าต่างเทอร์มินัล -

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

เอาต์พุตต่อไปนี้แสดงในคอนโซลเซิร์ฟเวอร์ นี่แสดงว่าเซิร์ฟเวอร์ด่วนกำลังทำงานบนพอร์ต 9000

server is up and running at 9000

หากคุณเปิดเบราว์เซอร์และพิมพ์ http://localhost:9000คุณจะได้รับหน้าจอต่อไปนี้ -

ในการหยุดเซิร์ฟเวอร์กด Ctrl + C.

ขั้นตอนที่ 2 - ติดตั้ง GraphQL และ Apollo Server

เมื่อกำหนดค่า Express แล้วขั้นตอนต่อไปคือการดาวน์โหลดการอ้างอิง GraphQL ต่อไปนี้ -

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

เราจะใช้ Apollo server v1.0 เนื่องจากเป็นรุ่นที่เสถียร พิมพ์คำสั่งต่อไปนี้เพื่อติดตั้งการอ้างอิงเหล่านี้ -

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

เราสามารถตรวจสอบได้ว่าการอ้างอิงเหล่านี้ติดตั้งสำเร็จหรือไม่โดยตรวจสอบไฟล์ package.json ไฟล์ที่เราสร้างไว้ก่อนหน้านี้

{
   "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"
   }
}

ขั้นตอนที่ 3 - กำหนด Schema

สคีมา GraphQL กำหนดชนิดของออบเจ็กต์ที่สามารถดึงข้อมูลจากบริการและฟิลด์ที่มีอยู่ สคีมาสามารถกำหนดได้โดยใช้GraphQL Schema Definition Language. ตอนนี้เพิ่มข้อมูลโค้ดต่อไปนี้ในไฟล์server.js ไฟล์ -

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

ที่นี่แบบสอบถามมีแอตทริบิวต์คำทักทายที่ส่งคืนค่าสตริง

ขั้นตอนที่ 4 - สร้างตัวแก้ไข

ขั้นตอนแรกในการสร้างตัวแก้ไขคือการเพิ่มโค้ดเพื่อประมวลผลฟิลด์การร้องขอสำหรับการทักทาย ระบุไว้ในไฟล์resolver. โครงสร้างของฟังก์ชันตัวแก้ไขต้องตรงกับสคีมา เพิ่มข้อมูลโค้ดต่อไปนี้ในไฟล์server.js ไฟล์.

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

ขั้นตอนที่สองคือการผูกสคีมาและตัวแก้ไขโดยใช้ makeExecutableSchema. ฟังก์ชันนี้ถูกกำหนดไว้ล่วงหน้าในโมดูล graphql-tools เพิ่มข้อมูลโค้ดต่อไปนี้ในไฟล์ server.js ไฟล์.

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

ขั้นตอนที่ 5 - กำหนดเส้นทางในการดึงข้อมูลจากแอปพลิเคชัน ReactJS / GraphiQL

เพิ่มข้อมูลโค้ดต่อไปนี้ในไฟล์ server.js ไฟล์ -

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

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

graphqlExpressฟังก์ชั่นช่วยในการลงทะเบียนเส้นทางhttp://localhost:9000/graphql. แอปพลิเคชัน ReactJS สามารถใช้จุดสิ้นสุดนี้เพื่อสืบค้นข้อมูล ในทำนองเดียวกันฟังก์ชันgraphqliExpressช่วยในการลงทะเบียนเส้นทางhttp://localhost:9000/graphiql. สิ่งนี้จะถูกใช้โดยไคลเอนต์เบราว์เซอร์ GraphiQL เพื่อทดสอบ API

รหัส server.js ที่สมบูรณ์มีดังต่อไปนี้ -

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}`))

ขั้นตอนที่ 6 - เริ่มแอปพลิเคชัน

ดำเนินการ server.js โดยใช้ Node.js ดังนี้ -

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

ขั้นตอนที่ 7 - ทดสอบ GraphQL API

เปิดเบราว์เซอร์และพิมพ์ http://localhost:9000/graphiql. ในแท็บแบบสอบถามของ GraphiQL ให้ป้อนข้อมูลต่อไปนี้ -

{
   greeting
}

การตอบสนองจากเซิร์ฟเวอร์ได้รับด้านล่าง -

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

ภาพต่อไปนี้แสดงให้เห็นถึงการตอบสนอง -

Note - โปรดตรวจสอบให้แน่ใจว่าใช้ Apollo Server เวอร์ชัน 1.0

GraphQL เป็นภาษาที่พิมพ์ยาก Type System กำหนดประเภทข้อมูลต่างๆที่สามารถใช้ในแอปพลิเคชัน GraphQL ระบบชนิดช่วยในการกำหนดสคีมาซึ่งเป็นสัญญาระหว่างไคลเอนต์และเซิร์ฟเวอร์ ประเภทข้อมูล GraphQL ที่ใช้กันทั่วไปมีดังนี้ -

ซีเนียร์ ประเภทและคำอธิบาย
1

Scalar

เก็บค่าเดียว

2

Object

แสดงชนิดของวัตถุที่สามารถดึงข้อมูลได้

3

Query

ประเภทจุดเข้าสู่ประเภทเฉพาะอื่น ๆ

4

Mutation

จุดเริ่มต้นสำหรับการจัดการข้อมูล

5

Enum

มีประโยชน์ในสถานการณ์ที่คุณต้องการให้ผู้ใช้เลือกจากรายการตัวเลือกที่กำหนด

ประเภทสเกลาร์

ประเภทสเกลาร์เป็นประเภทข้อมูลดั้งเดิมที่สามารถจัดเก็บได้เพียงค่าเดียว ประเภทสเกลาร์เริ่มต้นที่ GraphQL เสนอคือ -

  • Int - จำนวนเต็ม 32 บิตที่ลงนาม

  • Float - ลงนามค่าทศนิยมที่มีความแม่นยำสองเท่า

  • String - UTF - ลำดับอักขระ 8 ตัว

  • Boolean - จริงหรือเท็จ

  • ID - ตัวระบุที่ไม่ซ้ำกันซึ่งมักใช้เป็นตัวระบุเฉพาะเพื่อดึงวัตถุหรือเป็นกุญแจสำหรับแคช

ไวยากรณ์สำหรับการกำหนดประเภทสเกลาร์มีดังนี้ -

field: data_type

ตัวอย่างข้อมูลที่ระบุด้านล่างนี้กำหนดฟิลด์ที่ชื่อคำทักทายซึ่งส่งคืนค่าสตริง

greeting: String

ประเภทวัตถุ

ประเภทออบเจ็กต์เป็นประเภทที่ใช้บ่อยที่สุดในสคีมาและแสดงถึงกลุ่มของฟิลด์ แต่ละฟิลด์ภายในชนิดอ็อบเจ็กต์จะแมปกับประเภทอื่นซึ่งจะอนุญาตให้มีประเภทที่ซ้อนกัน กล่าวอีกนัยหนึ่งประเภทวัตถุประกอบด้วยประเภทสเกลาร์หรือประเภทวัตถุหลายประเภท

ไวยากรณ์สำหรับการกำหนดประเภทวัตถุมีดังต่อไปนี้ -

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

คุณสามารถพิจารณาข้อมูลโค้ดต่อไปนี้ -

--Define an object type--

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

--Defining a GraphQL schema--  

type Query
{
   stud_details:[Student]
}

ตัวอย่างที่ให้ไว้ข้างต้นกำหนดนักเรียนประเภทข้อมูลวัตถุ stud_detailsฟิลด์ในรากแบบสอบถามสคีจะกลับรายการของวัตถุนักศึกษา

ประเภทการสืบค้น

แบบสอบถาม GraphQL ใช้เพื่อดึงข้อมูล มันเหมือนกับการร้องขอทรัพยากรใน REST-based APIs เพื่อให้ง่ายประเภท Query คือคำขอที่ส่งจากแอปพลิเคชันไคลเอนต์ไปยังเซิร์ฟเวอร์ GraphQL GraphQL ใช้ไฟล์Schema Definition Language (SDL)เพื่อกำหนดการสืบค้น ประเภทการสืบค้นเป็นหนึ่งในประเภทระดับรากจำนวนมากใน GraphQL

ไวยากรณ์สำหรับการกำหนดแบบสอบถามมีดังต่อไปนี้ -

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

ตัวอย่างการกำหนดแบบสอบถาม -

type Query  {
   greeting: String
}

ประเภทการกลายพันธุ์

การกลายพันธุ์คือการดำเนินการที่ส่งไปยังเซิร์ฟเวอร์เพื่อ create, update หรือ deleteข้อมูล. สิ่งเหล่านี้คล้ายคลึงกับคำกริยา PUT, POST, PATCH และ DELETE เพื่อเรียก API ที่ใช้ REST

การกลายพันธุ์เป็นหนึ่งในประเภทข้อมูลระดับรูทใน GraphQL ประเภทแบบสอบถามกำหนดจุดเริ่มต้นสำหรับการดำเนินการดึงข้อมูลในขณะที่ประเภทการกลายพันธุ์ระบุจุดเข้าใช้งานสำหรับการดำเนินการจัดการข้อมูล

ไวยากรณ์สำหรับการกำหนดประเภทการกลายพันธุ์แสดงไว้ด้านล่าง -

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

ตัวอย่างเช่นเราสามารถกำหนดประเภทการกลายพันธุ์เพื่อเพิ่ม Student ใหม่ได้ดังนี้ -

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

ประเภท Enum

Enum คล้ายกับประเภทสเกลาร์ Enums มีประโยชน์ในสถานการณ์ที่ค่าสำหรับฟิลด์ต้องมาจากรายการตัวเลือกที่กำหนด

ไวยากรณ์สำหรับการกำหนดประเภท Enum คือ -

type enum_name{
   value1
   value2
}

ตัวอย่างต่อไปนี้แสดงให้เห็นว่าสามารถกำหนดประเภท enum ได้อย่างไร -

type Days_of_Week{
   SUNDAY
   MONDAY
   TUESDAY
   WEDNESDAY
   THURSDAY
   FRIDAY
   SATURDAY
}

ประเภทรายการ

รายการสามารถใช้เพื่อแสดงอาร์เรย์ของค่าเฉพาะประเภท รายการถูกกำหนดด้วยตัวปรับแต่งชนิด [] ที่ตัดประเภทอ็อบเจ็กต์สเกลาร์และ enums

คุณสามารถใช้ไวยากรณ์ต่อไปนี้เพื่อกำหนดประเภทรายการ -

field:[data_type]

ตัวอย่างด้านล่างกำหนดประเภทรายการสิ่งที่ต้องทำ -

type Query {
   todos: [String]
}

ประเภทที่ไม่เป็นโมฆะ

โดยค่าเริ่มต้นสเกลาร์หลักแต่ละประเภทสามารถตั้งค่าเป็น null ได้ กล่าวอีกนัยหนึ่งประเภทเหล่านี้สามารถส่งคืนค่าของประเภทที่ระบุหรือไม่มีค่าก็ได้ ในการแทนที่ค่าเริ่มต้นนี้และระบุว่าต้องกำหนดฟิลด์คุณสามารถเพิ่มเครื่องหมายอัศเจรีย์ (!) เข้ากับประเภทได้ สิ่งนี้ทำให้มั่นใจได้ถึงการมีอยู่ของค่าในผลลัพธ์ที่ส่งคืนโดยแบบสอบถาม

คุณสามารถใช้ไวยากรณ์ต่อไปนี้เพื่อกำหนดฟิลด์ที่ไม่เป็นค่าว่างได้ -

field:data_type!

ในตัวอย่างด้านล่างstud_idถูกประกาศให้เป็นฟิลด์บังคับ

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

สคีมา GraphQL เป็นหัวใจหลักของการใช้งานเซิร์ฟเวอร์ GraphQL อธิบายถึงฟังก์ชันการทำงานที่มีให้กับแอปพลิเคชันไคลเอนต์ที่เชื่อมต่อ เราสามารถใช้ภาษาการเขียนโปรแกรมใดก็ได้เพื่อสร้างสคีมา GraphQL และสร้างอินเทอร์เฟซรอบ ๆ

รันไทม์ GraphQL กำหนดสคีมาที่ใช้กราฟทั่วไปเพื่อเผยแพร่ความสามารถของบริการข้อมูลที่แสดง แอปพลิเคชันไคลเอนต์สามารถสอบถามสคีมาได้ภายในความสามารถ วิธีนี้แยกไคลเอ็นต์ออกจากเซิร์ฟเวอร์และอนุญาตให้ทั้งสองพัฒนาและปรับขนาดได้อย่างอิสระ

ในบทนี้เราใช้เซิร์ฟเวอร์ Apollo เพื่อดำเนินการค้นหา GraphQL makeExecutableSchema ฟังก์ชันใน graphql-tools ช่วยให้คุณสามารถผูก schema และ resolvers ได้

makeExecutableSchema Function Syntax

makeExecutableSchemaฟังก์ชันรับอาร์กิวเมนต์เดียว {} ของประเภทวัตถุ ไวยากรณ์สำหรับการใช้ฟังก์ชันนี้แสดงไว้ด้านล่าง -

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
});

ซีเนียร์ พารามิเตอร์และคำอธิบาย
1

typeDefs

นี่คืออาร์กิวเมนต์ที่จำเป็น แทนแบบสอบถาม GraphQL เป็นสตริง UTF-8

2

Resolvers

นี่คืออาร์กิวเมนต์ที่เป็นทางเลือก (วัตถุว่างโดยค่าเริ่มต้น) สิ่งนี้มีฟังก์ชันที่จัดการกับแบบสอบถาม

3

logger

นี่เป็นอาร์กิวเมนต์ที่เป็นทางเลือกและสามารถใช้เพื่อพิมพ์ข้อผิดพลาดไปยังคอนโซลเซิร์ฟเวอร์

4

parseOptions

นี่เป็นอาร์กิวเมนต์ทางเลือกและอนุญาตให้ปรับแต่งการแยกวิเคราะห์เมื่อระบุ typeDefs เป็นสตริง

5

allowUndefinedInResolve

นี่เป็นจริงตามค่าเริ่มต้น เมื่อตั้งค่าเป็นเท็จจะทำให้ฟังก์ชันการแก้ไขของคุณแสดงข้อผิดพลาดหากส่งคืนไม่ได้กำหนด

6

resolverValidationOptions

นี่เป็นอาร์กิวเมนต์ที่เป็นทางเลือกและยอมรับอ็อบเจ็กต์ที่มีคุณสมบัติบูลีน

7

inheritResolversFromInterfaces

นี่เป็นอาร์กิวเมนต์ที่เป็นทางเลือกและยอมรับอาร์กิวเมนต์บูลีนเพื่อตรวจสอบการสืบทอดอ็อบเจ็กต์ resolvers

ภาพประกอบ

ให้เราสร้างแอปพลิเคชันง่ายๆเพื่อทำความเข้าใจสคีมานี้ สิ่งนี้จะสร้างสคีมาสำหรับการสืบค้นรายชื่อนักเรียนจากเซิร์ฟเวอร์ ข้อมูลนักเรียนจะถูกเก็บไว้ในไฟล์แบบแบนและเราจะใช้โมดูลโหนดที่เรียกว่าnotarealdb เพื่อปลอมฐานข้อมูลและอ่านจากไฟล์แฟลต

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ชื่อ schema-app. เปลี่ยนไดเร็กทอรีของคุณเป็น schema-app จากเทอร์มินัล จากนั้นทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อมเพื่อทำการดาวน์โหลดและขั้นตอนการติดตั้งให้เสร็จสมบูรณ์

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในโฟลเดอร์โครงการ schema-app และเพิ่มรหัสต่อไปนี้ -

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

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

รากของสคีมาจะเป็นประเภทแบบสอบถาม แบบสอบถามมีสองฟิลด์ - คำทักทายและนักเรียนที่ส่งคืนสตริงและรายชื่อนักเรียนตามลำดับ Student ถูกประกาศเป็นประเภท Object เนื่องจากมีหลายฟิลด์ ฟิลด์ ID ถูกประกาศว่าไม่เป็นโมฆะ

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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

module.exports = {Query}

ที่นี่คำทักทายและนักเรียนคือตัวแก้ไขที่จัดการแบบสอบถาม students resolver functionส่งคืนรายชื่อนักเรียนจากชั้นการเข้าถึงข้อมูล ในการเข้าถึงฟังก์ชันตัวแก้ไขภายนอกโมดูลต้องส่งออกวัตถุแบบสอบถามโดยใช้module.exports.

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js และอ้างอิงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ขั้นตอนต่อไปคือดำเนินการคำสั่ง npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน เปิดเบราว์เซอร์และพิมพ์ URLhttp://localhost:9000/graphiql.

พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   greeting
   students {
      id
      firstName
      lastName
   }
}

แบบสอบถามจะแสดงผลลัพธ์ดังที่แสดงด้านล่าง -

Note- เราสามารถแทนที่ students.json ด้วยการเรียก RESTful API เพื่อดึงข้อมูลนักเรียนหรือแม้แต่ฐานข้อมูลจริงเช่น MySQL หรือ MongoDB GraphQL กลายเป็นกระดาษห่อบาง ๆ รอบ ๆ เลเยอร์แอปพลิเคชันเดิมของคุณเพื่อปรับปรุงประสิทธิภาพ

Resolver คือชุดของฟังก์ชันที่สร้างการตอบสนองสำหรับแบบสอบถาม GraphQL พูดง่ายๆคือตัวแก้ไขทำหน้าที่เป็นตัวจัดการแบบสอบถาม GraphQL ทุกฟังก์ชั่นตัวแก้ไขในสคีมา GraphQL ยอมรับสี่อาร์กิวเมนต์ตำแหน่งตามที่ระบุด้านล่าง -

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

ตัวอย่างของฟังก์ชันตัวแก้ไขแสดงอยู่ด้านล่าง -

//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);
}

ระบุไว้ด้านล่างนี้คืออาร์กิวเมนต์ตำแหน่งและคำอธิบาย -

ซีเนียร์ อาร์กิวเมนต์และคำอธิบาย
1

root

อ็อบเจ็กต์ที่มีผลลัพธ์ที่ส่งคืนจากตัวแก้ไขบนฟิลด์พาเรนต์

2

args

วัตถุที่มีอาร์กิวเมนต์ส่งผ่านเข้าไปในเขตข้อมูลในแบบสอบถาม

3

context

นี่คือออบเจ็กต์ที่ใช้ร่วมกันโดยตัวแก้ปัญหาทั้งหมดในข้อความค้นหาหนึ่ง ๆ

4

info

ประกอบด้วยข้อมูลเกี่ยวกับสถานะการดำเนินการของแบบสอบถามรวมถึงชื่อเขตข้อมูลเส้นทางไปยังเขตข้อมูลจากราก

รูปแบบผลลัพธ์ Resolver

Resolvers ใน GraphQL สามารถส่งคืนค่าประเภทต่างๆตามที่ระบุด้านล่าง -

ซีเนียร์ อาร์กิวเมนต์และคำอธิบาย
1

null or undefined

สิ่งนี้บ่งชี้ว่าไม่พบวัตถุ

2

array

จะใช้ได้เฉพาะในกรณีที่สคีมาระบุว่าผลลัพธ์ของฟิลด์ควรเป็นรายการ

3

promise

ตัวแก้ไขมักจะดำเนินการแบบอะซิงโครนัสเช่นการดึงข้อมูลจากฐานข้อมูลหรือ API แบ็กเอนด์ดังนั้นจึงสามารถคืนสัญญาได้

4

scalar or object

ตัวแก้ไขยังสามารถคืนค่าอื่น ๆ

ภาพประกอบ

ให้เราสร้างแอปพลิเคชั่นง่ายๆเพื่อทำความเข้าใจตัวแก้ไข สิ่งนี้จะสร้างสคีมาสำหรับการสืบค้นนักเรียนโดยใช้รหัสจากเซิร์ฟเวอร์ ข้อมูลนักเรียนจะถูกเก็บไว้ในไฟล์แบบแบนและเราจะใช้โมดูลโหนดที่เรียกว่าnotarealdb เพื่อปลอมฐานข้อมูลและอ่านจากไฟล์แบบแบน

ต่อไปนี้เป็นกระบวนการที่ชาญฉลาดในการสร้างแอปพลิเคชันง่ายๆ -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ชื่อ resolver-app. เปลี่ยนไดเร็กทอรีของคุณเป็นresolver-appจากขั้ว ต่อมาทำตามขั้นตอนที่ 3 ถึง 5 ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่มไฟล์ schema.graphql ในโฟลเดอร์โปรเจ็กต์ resolver-app และเพิ่มรหัสต่อไปนี้ -

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

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

แสดงให้เห็นว่าสคีไฟล์ที่ผู้ใช้สามารถสอบถามทักทายนักเรียนและstudentById ในการดึงข้อมูลนักเรียนที่มีรหัสเฉพาะเราใช้data type ID!ซึ่งแสดงฟิลด์ตัวระบุเฉพาะที่ไม่เป็นโมฆะ นักเรียนข้อมูลส่งกลับอาร์เรย์ของนักเรียนและทักทายผลตอบแทนค่าสตริงที่เรียบง่าย

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ที่นี่studentByIdใช้พารามิเตอร์สามตัว ตามที่กล่าวไว้ในบทนี้studentIdสามารถดึงมาจาก args; root จะมีวัตถุ Query เอง ในการส่งคืนนักเรียนที่ระบุเราต้องเรียกใช้เมธอด get ด้วยพารามิเตอร์ id ในคอลเล็กชันนักเรียน

นี่ทักทายนักเรียน studentByIdมี resolvers ที่จัดการแบบสอบถามstudents resolver functionส่งคืนรายชื่อนักเรียนจากชั้นการเข้าถึงข้อมูล ในการเข้าถึงฟังก์ชั่นตัวแก้ไขภายนอกโมดูลต้องส่งออกอ็อบเจ็กต์เคียวรีโดยใช้ module.exports

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่ง npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และป้อน url http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

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

ผลลัพธ์สำหรับแบบสอบถามด้านบนมีดังที่แสดงด้านล่าง -

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

การดำเนินการ GraphQL อาจเป็นการดำเนินการอ่านหรือเขียน แบบสอบถาม GraphQL ใช้เพื่ออ่านหรือดึงค่าในขณะที่ใช้การกลายพันธุ์เพื่อเขียนหรือโพสต์ค่า ไม่ว่าในกรณีใดการดำเนินการจะเป็นสตริงธรรมดาที่เซิร์ฟเวอร์ GraphQL สามารถแยกวิเคราะห์และตอบสนองด้วยข้อมูลในรูปแบบเฉพาะ รูปแบบการตอบกลับยอดนิยมที่มักใช้กับแอปพลิเคชันบนมือถือและเว็บคือ JSON

ไวยากรณ์ในการกำหนดแบบสอบถามมีดังนี้ -

//syntax 1
query query_name{ someField }

//syntax 2
{ someField }

ต่อไปนี้เป็นตัวอย่างของแบบสอบถาม -

//query with name myQuery
query myQuery{
   greeting
}

// query without any name
{
   greeting
}

จากตัวอย่างข้างต้นเห็นได้ชัดว่าคีย์เวิร์ดเคียวรีเป็นทางเลือก

การสืบค้น GraphQL ช่วยลดการดึงข้อมูลมากเกินไป แตกต่างจาก Restful API GraphQL อนุญาตให้ผู้ใช้ จำกัด ช่องที่ควรดึงมาจากเซิร์ฟเวอร์ ซึ่งหมายถึงข้อความค้นหาขนาดเล็กและปริมาณการใช้งานบนเครือข่ายน้อยลง ซึ่งจะช่วยลดเวลาตอบสนอง

ภาพประกอบ 1 - แบบสอบถามโมเดลนักเรียนด้วยฟิลด์ที่กำหนดเอง

ในตัวอย่างนี้เรามีชุดนักเรียนที่เก็บไว้ในไฟล์ json โมเดลนักเรียนแต่ละคนมีฟิลด์เช่น firstName, lastName และ id แต่ไม่มี fullName ในที่นี้เราจะพูดถึงวิธีการสร้างแบบสอบถามเพื่อดึงข้อมูลชื่อเต็มของนักเรียนทุกคน สำหรับสิ่งนี้เราต้องสร้างฟิลด์ fullName ในตัวแก้ไขสคีมาทั้งสอง

ให้เราดูวิธีการทำภาพประกอบโดยใช้ขั้นตอนด้านล่าง -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ชื่อ query-app. เปลี่ยนไดเร็กทอรีของคุณเป็นquery-appจากขั้ว ต่อมาทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในแอปแบบสอบถามโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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

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

หมายเหตุว่าไม่มีชื่อเต็มสนามในstudents.jsonไฟล์. แต่เราจำเป็นต้องเรียกชื่อเต็มของนักเรียนผ่านทางแบบสอบถาม ชื่อเต็มในกรณีนี้จะเป็นฟิลด์แบบกำหนดเองที่ไม่สามารถใช้ได้กับแหล่งข้อมูล

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.jsไฟล์. อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่ง  npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   students{
      id
      fullName
   }
}

คำตอบสำหรับแบบสอบถามได้รับด้านล่าง -

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

สร้างไฟล์ server.js และเพิ่มรหัสต่อไปนี้ -

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}`));

ดำเนินการคำสั่ง npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   students{
      id
      fullName
   }
}

คำตอบสำหรับแบบสอบถามได้รับด้านล่าง -

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

ภาพประกอบ 2 - แบบสอบถามที่ซ้อนกัน

ให้เราสร้างแบบสอบถามที่ซ้อนกันเพื่อดึงรายละเอียดของนักเรียนและรายละเอียดวิทยาลัยของพวกเขา เราจะทำงานกับโฟลเดอร์โครงการเดียวกัน

ขั้นตอนที่ 1 - แก้ไขสคีมา

ไฟล์สคีมามีฟิลด์นักเรียนอยู่แล้ว ให้เราเพิ่มวิทยาลัยภาคสนามและกำหนดประเภท

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

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

ขั้นตอนที่ 2 - แก้ไข resolver.js

เราจำเป็นต้องเพิ่มฟังก์ชันตัวแก้ไขของวิทยาลัยดังต่อไปนี้ ฟังก์ชันตัวแก้ไขของวิทยาลัยจะถูกเรียกใช้สำหรับวัตถุของนักเรียนแต่ละคนที่ส่งคืน พารามิเตอร์รากของจำแนกในกรณีนี้จะมีนักเรียน

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

ผลตอบแทนที่ได้จำแนกวิทยาลัยของนักเรียนแต่ละคนโดยการเรียกวิธีการรับของคอลเลกชันวิทยาลัยและผ่านcollegeId เรามีการเชื่อมโยงความสัมพันธ์ระหว่างนักศึกษาและวิทยาลัยผ่านcollegeId

ขั้นตอนที่ 3 - ทดสอบแอปพลิเคชัน

เปิดหน้าต่างเทอร์มินัลและไปที่โฟลเดอร์โครงการ พิมพ์คำสั่ง -npm start เปิดเบราว์เซอร์และป้อน URLhttp://localhost:9000/graphiql.

ป้อนแบบสอบถามต่อไปนี้ในหน้าต่าง GraphiQL -

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

การตอบสนองสำหรับแบบสอบถามมีดังต่อไปนี้ -

{
   "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
            }
         }
      ]
   }
}

ตัวแปรการสืบค้นคืออะไร?

หากแบบสอบถามมีค่าไดนามิกที่จะส่งผ่านให้แทนค่าไดนามิกเหล่านี้โดยใช้ตัวแปร ดังนั้นแบบสอบถามสามารถใช้ซ้ำได้โดยแอปพลิเคชันไคลเอนต์

ภาพประกอบ

ให้เราสร้างแอปพลิเคชันง่ายๆเพื่อทำความเข้าใจตัวแปรคิวรี

ขั้นตอนที่ 1 - แก้ไขไฟล์ Schema

เพิ่มช่องsayHelloซึ่งรับพารามิเตอร์สตริงและส่งคืนสตริง ค่าชื่อจะเป็นแบบไดนามิกในแอปพลิเคชันไคลเอนต์

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

ขั้นตอนที่ 2 - แก้ไขไฟล์ resolver.js

เพิ่มตัวแก้ไขsayHelloซึ่งรับพารามิเตอร์ดังต่อไปนี้ -

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

ขั้นตอนที่ 3 - ประกาศตัวแปรการค้นหาใน GraphiQL

ตัวแปรถูกประกาศด้วย $ ตามด้วยชื่อของตัวแปร ตัวอย่างเช่น $ myname_Variable

เมื่อมีการประกาศ $ myname_Variable แล้วจะต้องใช้กับไวยากรณ์การสืบค้นที่มีชื่อ แบบสอบถาม myQuery รับค่าสตริงและส่งต่อไปยัง sayHello ดังที่แสดงด้านล่าง -

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

ตั้งค่าสำหรับ $ myname_Variable เป็นออบเจ็กต์ JSON ในส่วนตัวแปรการสืบค้นของไคลเอ็นต์ GraphiQL

{
   "myname_Variable": "Mohtashim"
}

ผลลัพธ์ของโค้ดด้านบนมีดังนี้ -

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

วิธีใช้ Query Variable กับ Enum

ให้เราดูวิธีใช้ตัวแปรแบบสอบถามเมื่อพารามิเตอร์ฟิลด์คือ enum type.

ขั้นตอนที่ 1 - แก้ไขไฟล์ schema.graphql

enum ColorType {
   RED
   BLUE
   GREEN
}

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

setFavouriteColorฟังก์ชั่นใช้เวลา enum เป็น input และส่งกลับค่าสตริง

ขั้นตอนที่ 2 - แก้ไขไฟล์ resolvers.js

ฟังก์ชั่นจำแนกsetFavouriteColorใช้เวลารากและargs ค่า enum ที่ส่งผ่านไปยังฟังก์ชันขณะรันไทม์สามารถเข้าถึงได้ผ่านพารามิเตอร์ args

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

ขั้นตอนที่ 3 - ประกาศตัวแปรการค้นหาใน GraphiQL

มีการตั้งชื่อแบบสอบถาม query_to_setColorซึ่งรับตัวแปรของชื่อ color_variable ของ ColorType ตัวแปรนี้ถูกส่งต่อไปยังเมธอด setFavouriteColor

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

ในส่วนตัวแปรการค้นหาของ GraphiQL ให้พิมพ์รหัสต่อไปนี้ -

{
   "color_variable":"RED"
}

คำตอบดังแสดงด้านล่าง -

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

ในบทนี้เราจะเรียนรู้การค้นหาการกลายพันธุ์ใน GraphQL

แบบสอบถามการกลายพันธุ์จะแก้ไขข้อมูลในที่เก็บข้อมูลและส่งคืนค่า สามารถใช้เพื่อแทรกอัปเดตหรือลบข้อมูล การกลายพันธุ์ถูกกำหนดให้เป็นส่วนหนึ่งของสคีมา

ไวยากรณ์ของแบบสอบถามการกลายพันธุ์แสดงไว้ด้านล่าง -

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

ภาพประกอบ

ให้เราเข้าใจวิธีการเพิ่มระเบียนนักเรียนใหม่ในที่เก็บข้อมูลโดยใช้แบบสอบถามการกลายพันธุ์

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์โครงการโดยใช้ชื่อ mutation-app เปลี่ยนไดเร็กทอรีของคุณเป็น mutation-app จากเทอร์มินัล ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างไฟล์ schema.graphql

เพิ่ม schema.graphql ไฟล์ในแอปการกลายพันธุ์ของโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

type Query {
   greeting:String
}

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

โปรดสังเกตว่าฟังก์ชัน createStudent ส่งคืนชนิด String นี่คือตัวระบุเฉพาะ (ID) ซึ่งสร้างขึ้นหลังจากสร้างนักเรียน

ขั้นตอนที่ 3 - สร้างไฟล์ resolver.js

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ฟังก์ชันการกลายพันธุ์ชี้ไปที่คอลเล็กชันของนักเรียนในที่เก็บข้อมูล หากต้องการเพิ่มนักเรียนใหม่ให้เรียกใช้วิธีการสร้างในคอลเล็กชันนักเรียน argsวัตถุจะมีพารามิเตอร์ที่จะถูกส่งผ่านในแบบสอบถาม วิธีสร้างคอลเล็กชันนักเรียนจะส่งคืน id ของอ็อบเจ็กต์นักเรียนที่สร้างขึ้นใหม่

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.jsไฟล์. อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่ง npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

ขั้นตอนต่อไปคือการเปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

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

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

แบบสอบถามด้านบนจะสร้างวัตถุนักเรียนในไฟล์ student.json แบบสอบถามจะส่งคืนตัวระบุที่ไม่ซ้ำกัน การตอบสนองของแบบสอบถามดังแสดงด้านล่าง -

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

ในการตรวจสอบว่าวัตถุนักเรียนถูกสร้างขึ้นหรือไม่เราสามารถใช้แบบสอบถาม studentById คุณยังสามารถเปิดไฟล์ students.json จากโฟลเดอร์ข้อมูลเพื่อตรวจสอบรหัส

ในการใช้แบบสอบถาม studentById ให้แก้ไขไฟล์ schema.graphql ตามที่ระบุด้านล่าง -

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

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

แก้ไขไฟล์ resolver.js ไฟล์ตามที่ระบุด้านล่าง -

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}

ให้ด้านล่างนี้คือแบบสอบถามเพื่อรับนักเรียนโดยรหัสเฉพาะที่ส่งคืนจากแบบสอบถามการกลายพันธุ์ -

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

การตอบสนองจากเซิร์ฟเวอร์มีดังนี้ -

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

การส่งคืนวัตถุในการกลายพันธุ์

แนวทางปฏิบัติที่ดีที่สุดในการส่งคืนวัตถุในการกลายพันธุ์ ตัวอย่างเช่นแอปพลิเคชันไคลเอนต์ต้องการดึงรายละเอียดของนักเรียนและวิทยาลัย ในกรณีนี้แทนที่จะส่งคำขอที่แตกต่างกันสองคำขอเราสามารถสร้างแบบสอบถามที่ส่งคืนวัตถุที่มีนักเรียนและรายละเอียดของวิทยาลัย

ขั้นตอนที่ 1 - แก้ไขไฟล์ Schema

เพิ่มเมธอดใหม่ชื่อ addStudent ซึ่งส่งคืนวัตถุในประเภทการกลายพันธุ์ของ schema.graphql.

ให้เราเรียนรู้วิธีเข้าถึงรายละเอียดของวิทยาลัยผ่านรายละเอียดของนักเรียน เพิ่มประเภทวิทยาลัยในไฟล์สคีมา

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
}

ขั้นตอนที่ 2 - อัปเดตไฟล์ resolvers.js

อัปเดตไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ขั้นตอนที่ 3 - เริ่มเซิร์ฟเวอร์และพิมพ์แบบสอบถามคำขอใน GraphiQL

ต่อไปเราจะเริ่มต้นเซิร์ฟเวอร์และขอแบบสอบถามใน GraphiQL ด้วยรหัสต่อไปนี้ -

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

ข้อความค้นหาข้างต้นจะเพิ่มนักเรียนใหม่และดึงวัตถุของนักเรียนพร้อมกับวัตถุของวิทยาลัย ซึ่งจะช่วยประหยัดการเดินทางไปกลับเซิร์ฟเวอร์

คำตอบมีดังต่อไปนี้ -

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

ในขณะที่เพิ่มหรือแก้ไขข้อมูลสิ่งสำคัญคือต้องตรวจสอบความถูกต้องของข้อมูลที่ผู้ใช้ป้อน ตัวอย่างเช่นเราอาจต้องตรวจสอบให้แน่ใจว่าค่าของเขตข้อมูลไม่เป็นค่าว่างเสมอไป เราสามารถใช้! (non-nullable) พิมพ์ marker ใน GraphQL เพื่อทำการตรวจสอบความถูกต้องดังกล่าว

ไวยากรณ์สำหรับการใช้ ! ประเภทเครื่องหมายมีดังต่อไปนี้ -

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

ไวยากรณ์ข้างต้นช่วยให้แน่ใจว่าฟิลด์ทั้งหมดไม่เป็นโมฆะ

หากเราต้องการใช้กฎเพิ่มเติมเช่นการตรวจสอบความยาวของสตริงหรือตรวจสอบว่าตัวเลขอยู่ในช่วงที่กำหนดหรือไม่เราสามารถกำหนดตัวตรวจสอบความถูกต้องที่กำหนดเองได้ ตรรกะการตรวจสอบความถูกต้องที่กำหนดเองจะเป็นส่วนหนึ่งของฟังก์ชันตัวแก้ไข ให้เราเข้าใจสิ่งนี้ด้วยความช่วยเหลือของตัวอย่าง

ภาพประกอบ - การใช้งาน Custom Validators

ให้เราสร้างแบบฟอร์มสมัครด้วยการตรวจสอบความถูกต้องพื้นฐาน แบบฟอร์มจะมีฟิลด์อีเมลชื่อและรหัสผ่าน

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ชื่อ validation-app. เปลี่ยนไดเร็กทอรีเป็น validation-app จากเทอร์มินัล ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในโฟลเดอร์โครงการ validation-app และเพิ่มรหัสต่อไปนี้ -

type Query {
   greeting:String
}

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

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

Note- เราสามารถใช้ประเภทการป้อนข้อมูล SignUpInput เพื่อลดจำนวนพารามิเตอร์ในฟังก์ชันการลงชื่อสมัครใช้ ดังนั้นฟังก์ชัน signUp จึงใช้พารามิเตอร์ประเภท SignUpInput เพียงพารามิเตอร์เดียว

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ฟังก์ชั่นตัวแก้ไขการลงทะเบียนยอมรับอีเมลพารามิเตอร์รหัสผ่านและชื่อแรก สิ่งเหล่านี้จะถูกส่งผ่านตัวแปรอินพุตเพื่อให้สามารถเข้าถึงได้ผ่าน args.input

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่งnpm startในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ในที่นี้เราจะใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และป้อน URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

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

เนื่องจากฟังก์ชัน input to signup เป็นประเภทที่ซับซ้อนเราจึงจำเป็นต้องใช้ตัวแปรการสืบค้นใน graphiql สำหรับสิ่งนี้เราต้องตั้งชื่อให้กับแบบสอบถามก่อนและเรียกมันว่า doSignUp, $ input เป็นตัวแปรการสืบค้น

ต้องป้อนตัวแปรการสืบค้นต่อไปนี้ในแท็บตัวแปรการค้นหาของ graphiql -

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

อาร์เรย์ข้อผิดพลาดมีรายละเอียดของข้อผิดพลาดในการตรวจสอบดังที่แสดงด้านล่าง -

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

เราต้องป้อนข้อมูลที่เหมาะสมสำหรับแต่ละฟิลด์ตามที่ระบุด้านล่าง -

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

คำตอบมีดังนี้ -

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

ในแบบสอบถามด้านล่างนี้เราไม่ได้กำหนดรหัสผ่านใด ๆ

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

หากไม่ได้ระบุฟิลด์ที่จำเป็นเซิร์ฟเวอร์ qraphql จะแสดงข้อผิดพลาดต่อไปนี้ -

{
   "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
            }
         ]
      }
   ]
}

เว็บแอปพลิเคชันส่งและดึงข้อมูลแบบอะซิงโครนัส (ในพื้นหลัง) AJAX อนุญาตให้เว็บไซต์โหลดเนื้อหาลงบนหน้าจอโดยไม่ต้องรีเฟรชหน้า jQuery มีวิธีการต่างๆสำหรับฟังก์ชัน AJAX ซึ่งทำให้การใช้งาน AJAX ง่ายขึ้น ในบทนี้เราจะเรียนรู้วิธีที่เราสามารถรวม GraphQL กับ jQuery

พิจารณาแอปพลิเคชันที่ใช้สถาปัตยกรรมไคลเอนต์เซิร์ฟเวอร์ เราสามารถสร้างหน้าเว็บส่วนหน้าที่ร้องขอข้อมูลจากเซิร์ฟเวอร์ GraphQL หน้าเว็บจะทำการเรียก AJAX โดยใช้ jQuery ไปยังเซิร์ฟเวอร์ GraphQL

ในการรวม GraphQL เข้ากับ JQuery ให้เราตรวจสอบส่วนหัวของคำขอ GraphiQL และทำความเข้าใจกับพารามิเตอร์การร้องขอ

เริ่ม hello-worldแอพ (ดูบทที่ 6 สำหรับภาพประกอบที่เกี่ยวข้อง) พิมพ์คำค้นหา graphql {greeting} ในหน้าต่าง GraphiQL คลิกขวาและตรวจสอบหรือกด (ctrl + shift + I) บน chrome เพื่อไปที่แท็บเครือข่ายดังที่แสดงด้านล่าง -

จากที่เรียบง่าย hello-world ตัวอย่างเช่นเราสามารถเข้าใจได้ http method ใช้คือ POST. ตอนนี้ในเบราว์เซอร์ให้เลื่อนลงไปที่ส่วนหัวเพื่อดู  น้ำหนักบรรทุกคำขอ

เมื่อคุณคลิกที่ view codeคุณจะเห็นสิ่งต่อไปนี้ในส่วนเพย์โหลดคำขอของ chrome

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

โปรดสังเกต URL ของคำขอด้วย http://localhost:9000/graphql ที่ควรเรียกจากแอปพลิเคชันไคลเอนต์

ภาพประกอบ

ให้เราเข้าใจวิธีการรวม GraphQL กับ JQuery โดยใช้กระบวนการที่ชาญฉลาด

การตั้งค่าเซิร์ฟเวอร์

เราจะเรียนรู้การตั้งค่าเซิร์ฟเวอร์โดยใช้ขั้นตอนต่อไปนี้ -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ชื่อ jquery-server-app. เปลี่ยนไดเร็กทอรีของคุณเป็น jquery-server-app จากเทอร์มินัล ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่มไฟล์ schema.graphql ในโฟลเดอร์โครงการ jquery-server-app และเพิ่มรหัสต่อไปนี้ -

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

ไฟล์ได้กำหนดสองแบบสอบถาม greeting และ sayHello. แบบสอบถาม sayHello ยอมรับพารามิเตอร์สตริงและส่งคืนสตริงอื่น พารามิเตอร์ของฟังก์ชัน sayHello () ไม่เป็นโมฆะ

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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

ที่นี่ greeting และ sayHelloเป็นตัวแก้ไขสองตัว ในตัวแก้ไข sayHello ค่าที่ส่งไปยังพารามิเตอร์ name สามารถเข้าถึงได้ผ่าน args ในการเข้าถึงฟังก์ชันตัวแก้ไขภายนอกโมดูลต้องส่งออกวัตถุแบบสอบถามโดยใช้module.exports.

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่งnpm startในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

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

การตอบสนองจากเซิร์ฟเวอร์เป็นไปตามที่ระบุด้านล่าง -

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

การตั้งค่าไคลเอนต์

เนื่องจากเราได้ตั้งค่าเซิร์ฟเวอร์แล้วตอนนี้เราจะเรียนรู้วิธีการตั้งค่าไคลเอนต์

ขั้นตอนที่ 1 - สร้างโฟลเดอร์ jquery-client-app ใหม่นอกโฟลเดอร์โครงการปัจจุบัน

ขั้นแรกเราจะสร้างโฟลเดอร์ชื่อ jquery-client-app นอกโฟลเดอร์โครงการ

ขั้นตอนที่ 2 - สร้างหน้า HTML index.html สำหรับการรวม jQuery

เราจะสร้างแอปพลิเคชันไคลเอนต์ใน jquery และเรียกใช้ทั้งสองวิธี ต่อไปนี้เป็นรหัสสำหรับ index.html ไฟล์.  index.html เพจส่งคำขอไปยังเซิร์ฟเวอร์เมื่อปุ่ม - Greet และ SayHelloถูกคลิก เราจะทำการร้องขอแบบอะซิงโครนัสโดยใช้ฟังก์ชัน $ .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>

เปิดไฟล์นี้ในเบราว์เซอร์และคลิกที่ปุ่มเพื่อดูการตอบสนอง ผลลัพธ์จะเป็นไปตามที่ระบุด้านล่าง -

React เป็นไลบรารี Javascript สำหรับสร้างส่วนต่อประสานผู้ใช้ บทนี้จะอธิบายถึงวิธีการรวม GraphQL กับแอปพลิเคชัน React

ภาพประกอบ

วิธีที่เร็วที่สุดในการตั้งค่าโครงการตอบกลับคือการใช้   เครื่องมือCreate React App ในส่วนต่อไปเราจะเรียนรู้วิธีการตั้งค่าทั้งเซิร์ฟเวอร์และไคลเอนต์

การตั้งค่าเซิร์ฟเวอร์

สำหรับการตั้งค่าเซิร์ฟเวอร์ให้ทำตามขั้นตอนด้านล่าง -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ react-server-app. เปลี่ยนไดเร็กทอรีของคุณเป็น react-server-app จากขั้ว ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในโฟลเดอร์โครงการ react-server-app และเพิ่มรหัสต่อไปนี้ -

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

ไฟล์ได้กำหนดคำค้นหาไว้สองรายการ - ทักทายและพูดสวัสดี แบบสอบถาม sayHello ยอมรับพารามิเตอร์สตริงและส่งคืนสตริงอื่น พารามิเตอร์ของฟังก์ชัน sayHello () ไม่เป็นโมฆะ

ขั้นตอนที่ 3 - สร้างตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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

ที่นี่ทักทายและพูดสวัสดีเป็นสองตัวแก้ไข ในตัวแก้ไข sayHello ค่าที่ส่งไปยังพารามิเตอร์ name สามารถเข้าถึงได้ผ่าน args ในการเข้าถึงฟังก์ชั่นตัวแก้ไขภายนอกโมดูลต้องส่งออกอ็อบเจ็กต์เคียวรีโดยใช้ module.exports

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่งnpm startในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

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

การตอบสนองจากเซิร์ฟเวอร์ได้รับด้านล่าง -

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

การตั้งค่าไคลเอนต์

เปิดเทอร์มินัลใหม่สำหรับไคลเอนต์ ควรให้เทอร์มินัลเซิร์ฟเวอร์ทำงานต่อไปก่อนที่จะเรียกใช้ไคลเอนต์ แอปพลิเคชัน React จะทำงานบนพอร์ตหมายเลข 3000 และแอปพลิเคชันเซิร์ฟเวอร์บนพอร์ตหมายเลข 9000

ขั้นตอนที่ 1 - สร้างโครงการตอบสนองสวัสดีลูกค้าทั่วโลก

ในไคลเอนต์เทอร์มินัลพิมพ์คำสั่งต่อไปนี้ -

npx create-react-app hello-world-client

สิ่งนี้จะติดตั้งทุกสิ่งที่จำเป็นสำหรับแอปพลิเคชันการตอบสนองทั่วไป npx ยูทิลิตี้และ create-react-appเครื่องมือสร้างโครงการด้วยชื่อสวัสดีลูกค้าทั่วโลก เมื่อการติดตั้งเสร็จสิ้นให้เปิดโครงการใน VSCode

ขั้นตอนที่ 2 - เริ่มสวัสดีลูกค้าทั่วโลก

เปลี่ยนเส้นทางโฟลเดอร์ปัจจุบันในเทอร์มินัลเป็น hello-world-client พิมพ์ npm start เพื่อเปิดตัวโปรเจ็กต์ การดำเนินการนี้จะเรียกใช้เซิร์ฟเวอร์การพัฒนาที่พอร์ต 3000 และจะเปิดเบราว์เซอร์โดยอัตโนมัติและโหลดหน้าดัชนี

สิ่งนี้แสดงในภาพหน้าจอด้านล่าง -

ขั้นตอนที่ 3 - แก้ไขส่วนประกอบแอพ

ในโฟลเดอร์ App.js ภายใน src ให้เพิ่มฟังก์ชันสองอย่างคือโหลดคำทักทายและอีกฟังก์ชันเพื่อโหลดข้อความ sayHello

ต่อไปนี้เป็นฟังก์ชัน loadGreeting ซึ่งส่งแบบสอบถาม GraphQL สำหรับการทักทาย

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")
}

ต่อไปนี้คือไฟล์ loadSayhello ฟังก์ชันที่ส่งแบบสอบถาม GraphQL สำหรับ 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}")}`})
   })
}

ที่สมบูรณ์ App.js ไฟล์แสดงด้านล่าง -

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;

เมื่อทั้งสองแอปพลิเคชันทำงานให้คลิกที่ปุ่มทักทาย จากนั้นป้อนชื่อในช่องข้อความและคลิกที่ปุ่มพูดสวัสดี ผลลัพธ์จะเป็นไปตามที่ระบุด้านล่าง -

เราได้ใช้ Apollo Server เพื่อสร้างข้อกำหนดของ graphql ที่ฝั่งเซิร์ฟเวอร์ มันง่ายและรวดเร็วในการสร้างเซิร์ฟเวอร์ GraphQL ที่พร้อมใช้งานจริง ตอนนี้ให้เราเข้าใจฝั่งไคลเอ็นต์

Apollo Client เป็นวิธีที่ดีที่สุดในการใช้ GraphQL เพื่อสร้างแอปพลิเคชันไคลเอนต์ ไคลเอนต์ได้รับการออกแบบมาเพื่อช่วยให้นักพัฒนาสร้าง UI ที่ดึงข้อมูลด้วย GraphQL ได้อย่างรวดเร็วและสามารถใช้กับส่วนหน้าของ JavaScript ใดก็ได้

Apollo Client รองรับแพลตฟอร์มต่อไปนี้ -

ซีเนียร์ แพลตฟอร์มและกรอบงาน
1

Javascript

ปฏิกิริยาเชิงมุม, Vue, ดาวตก, Ember

2

WebComponents

พอลิเมอร์ไลท์อพอลโล

3

Native Mobile

Native Android พร้อม Java, Native iOS พร้อม Swift

การแคชเป็นหนึ่งในคุณสมบัติหลักของ Apollo Client apollo-boost เป็นแพ็คเกจอำนวยความสะดวกที่นำมาซึ่งการพึ่งพาอื่น ๆ อีกมากมาย

ภาพประกอบ

ให้เราดูวิธีใช้ Apollo Client เพื่อสร้างแอปพลิเคชันไคลเอนต์โดยใช้ขั้นตอนต่อไปนี้ -

การตั้งค่าเซิร์ฟเวอร์

เราต้องทำตามขั้นตอนด้านล่างเพื่อตั้งค่าเซิร์ฟเวอร์ -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ apollo-server-app เปลี่ยนไดเร็กทอรีของคุณเป็น apollo-server-app จากขั้ว จากนั้นทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในโฟลเดอร์โครงการ apollo-server-app และเพิ่มรหัสต่อไปนี้ -

type Query
{
   students:[Student]
}

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

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

ขั้นตอนที่ 3 - เพิ่มตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.jsไฟล์. อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่ง  npm start  ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ในที่นี้เราจะใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์แบบสอบถามต่อไปนี้ในตัวแก้ไข

{
   students{
      id
      firstName
      college{
         name
      }
   }
}

การตอบสนองสำหรับแบบสอบถามมีดังต่อไปนี้ -

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

การตั้งค่าไคลเอนต์

เปิดเทอร์มินัลใหม่สำหรับไคลเอนต์ ควรให้เทอร์มินัลเซิร์ฟเวอร์ทำงานต่อไปก่อนที่จะเรียกใช้ไคลเอนต์ แอปพลิเคชัน React จะทำงานบนพอร์ตหมายเลข 3000 และแอปพลิเคชันเซิร์ฟเวอร์บนพอร์ตหมายเลข 9000

ขั้นตอนที่ 1 - สร้างแอปพลิเคชันตอบสนอง

ในไคลเอนต์เทอร์มินัลพิมพ์คำสั่งต่อไปนี้ -

npx create-react-app hello-world-client

สิ่งนี้จะติดตั้งทุกสิ่งที่จำเป็นสำหรับแอปพลิเคชันการตอบสนองทั่วไป ยูทิลิตี้ npx และเครื่องมือสร้างปฏิกิริยาแอปสร้างโปรเจ็กต์ที่มีชื่อhello-world-client. เมื่อการติดตั้งเสร็จสิ้นให้เปิดโครงการใน VSCode

ขั้นตอนที่ 2 - เริ่มสวัสดีลูกค้าทั่วโลก

เปลี่ยนเส้นทางโฟลเดอร์ปัจจุบันในเทอร์มินัลเป็น hello-world-client. พิมพ์ npm start เพื่อเปิดตัวโปรเจ็กต์ การดำเนินการนี้จะเรียกใช้เซิร์ฟเวอร์การพัฒนาที่พอร์ต 3000 และจะเปิดเบราว์เซอร์โดยอัตโนมัติและโหลดหน้าดัชนี

สิ่งนี้แสดงในภาพหน้าจอด้านล่าง -

ขั้นตอนที่ 3 - ติดตั้ง Apollo Client Libraries

ในการติดตั้ง Apollo Client ให้เปิดเทอร์มินัลใหม่และอยู่ในเส้นทางโฟลเดอร์โครงการปัจจุบัน พิมพ์คำสั่งต่อไปนี้ -

npm install apollo-boost graphql

สิ่งนี้จะดาวน์โหลดไลบรารี graphql สำหรับฝั่งไคลเอ็นต์และแพ็คเกจ Apollo Boost เราสามารถตรวจสอบสิ่งนี้ได้โดยพิมพ์ npm view ใน apollo-boost dependencies สิ่งนี้จะมีการอ้างอิงมากมายดังที่แสดงด้านล่าง -

{
   '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'
}

เราจะเห็นได้ชัดเจนว่ามีการติดตั้งไลบรารี Apollo-Client

ขั้นตอนที่ 4 - แก้ไขส่วนประกอบแอพในไฟล์ index.js

ด้วย Apollo Client เราสามารถเรียกเซิร์ฟเวอร์ได้โดยตรงโดยไม่ต้องใช้ fetch API นอกจากนี้ไม่ควรฝังข้อความค้นหาและการกลายพันธุ์ไว้ในสตริงที่สร้างด้วยเครื่องหมายขีดหลัง นี่เป็นเพราะไฟล์gqlฟังก์ชั่นแยกวิเคราะห์แบบสอบถามโดยตรง ซึ่งหมายความว่าโปรแกรมเมอร์สามารถเขียนแบบสอบถามได้โดยตรงในลักษณะเดียวกันเมื่อเขียนแบบสอบถามในเครื่องมือ GraphiQL gql เป็นฟังก์ชันแท็กซึ่งจะแยกวิเคราะห์สตริงแม่แบบที่เขียนด้วยเครื่องหมายขีดหลังไปยังวัตถุแบบสอบถาม graphql วิธีการสอบถาม Apollo Client ส่งคืนคำสัญญา

ข้อมูลโค้ดต่อไปนี้แสดงวิธีการนำเข้า 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()
});

ในบทที่แล้วเราได้พูดถึงวิธีใช้ fetch API สำหรับคำขอ HTTP รหัสต่อไปนี้แสดงวิธีใช้gqlฟังก์ชัน loadStudentsAsync ฟังก์ชันใช้ไคลเอนต์ graphql เพื่อค้นหาเซิร์ฟเวอร์

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

คุณจะต้องเก็บไฟล์ index.js ใน srcโฟลเดอร์และ index.html ในโฟลเดอร์สาธารณะ ไฟล์อื่น ๆ ทั้งหมดที่สร้างขึ้นโดยอัตโนมัติสามารถลบออกได้

โครงสร้างไดเร็กทอรีได้รับด้านล่าง -

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

ต่อไปนี้คือไฟล์ index.js ในแอปพลิเคชันตอบสนอง -

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'));

แอปพลิเคชันตอบกลับจะโหลดนักเรียนจากเซิร์ฟเวอร์ GraphQL เมื่อเราคลิกที่ปุ่ม loadStudents ดังที่แสดงด้านล่าง -

การพิสูจน์ตัวตนคือกระบวนการหรือการดำเนินการในการยืนยันตัวตนของผู้ใช้หรือกระบวนการ เป็นสิ่งสำคัญที่แอปพลิเคชันจะพิสูจน์ตัวตนผู้ใช้เพื่อให้แน่ใจว่าข้อมูลนั้นไม่มีให้สำหรับผู้ใช้ที่ไม่ระบุชื่อ ในส่วนนี้เราจะเรียนรู้วิธีการรับรองความถูกต้องไคลเอ็นต์ GraphQL

ด่วนจว

ในตัวอย่างนี้เราจะใช้ jQuery เพื่อสร้างแอปพลิเคชันไคลเอนต์ ในการตรวจสอบคำขอเราจะใช้ express-jwt โมดูลทางฝั่งเซิร์ฟเวอร์

โมดูล express-jwt เป็นมิดเดิลแวร์ที่ให้คุณตรวจสอบสิทธิ์คำขอ HTTP โดยใช้โทเค็น JWT JSON Web Token (JWT) เป็นสตริงแบบยาวที่ระบุผู้ใช้ที่ล็อกอิน

เมื่อผู้ใช้ล็อกอินสำเร็จเซิร์ฟเวอร์จะสร้างโทเค็น JWT โทเค็นนี้ระบุบันทึกอย่างชัดเจน กล่าวอีกนัยหนึ่งโทเค็นคือการแสดงตัวตนของผู้ใช้ ดังนั้นในครั้งต่อไปเมื่อไคลเอนต์มาที่เซิร์ฟเวอร์จะต้องนำเสนอโทเค็นนี้เพื่อรับทรัพยากรที่ต้องการ ไคลเอนต์สามารถเป็นได้ทั้งแอปพลิเคชันมือถือหรือเว็บแอปพลิเคชัน

ภาพประกอบ

เราจะทำตามขั้นตอนที่ชาญฉลาดเพื่อทำความเข้าใจภาพประกอบนี้

การตั้งค่าเซิร์ฟเวอร์

ต่อไปนี้เป็นขั้นตอนในการตั้งค่าเซิร์ฟเวอร์ -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ auth-server-app. เปลี่ยนไดเร็กทอรีของคุณเป็น auth-server-app จากขั้ว ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

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

ขั้นตอนที่ 3 - เพิ่มตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

ตัวแก้ไขจะตรวจสอบว่าอ็อบเจ็กต์ผู้ใช้ที่พิสูจน์ตัวตนมีอยู่ในอ็อบเจ็กต์บริบทของ GraphQL หรือไม่ จะเพิ่มข้อยกเว้นหากไม่มีผู้ใช้ที่ผ่านการรับรองความถูกต้อง

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}

ขั้นตอนที่ 4 - สร้างไฟล์ Server.js

มิดเดิลแวร์การตรวจสอบสิทธิ์รับรองความถูกต้องของผู้โทรโดยใช้ JSON Web Token URL สำหรับการพิสูจน์ตัวตนคือ http://localhost:9000/login.

นี่คือการดำเนินการโพสต์ ผู้ใช้ต้องส่งอีเมลและรหัสผ่านซึ่งจะได้รับการตรวจสอบจากแบ็กเอนด์ หากโทเค็นที่ถูกต้องถูกสร้างขึ้นโดยใช้เมธอด jwt.sign ไคลเอนต์จะต้องส่งสิ่งนี้ในส่วนหัวสำหรับการร้องขอในภายหลัง

หากโทเค็นถูกต้อง req.user จะถูกตั้งค่าด้วยออบเจ็กต์ JSON ที่ถอดรหัสเพื่อใช้โดยมิดเดิลแวร์ในภายหลังสำหรับการอนุญาตและการควบคุมการเข้าถึง

โค้ดต่อไปนี้ใช้สองโมดูล - jsonwebtoken และ express-jwt เพื่อพิสูจน์ตัวตนคำขอ -

  • เมื่อผู้ใช้คลิกที่ไฟล์ greetจะมีการร้องขอเส้นทาง / graphql หากผู้ใช้ไม่ได้รับการรับรองความถูกต้องเขาจะได้รับแจ้งให้ตรวจสอบสิทธิ์ตัวเอง

  • ผู้ใช้จะได้รับแบบฟอร์มที่ยอมรับรหัสอีเมลและรหัสผ่าน ในตัวอย่างของเราเส้นทาง / เข้าสู่ระบบมีหน้าที่ในการพิสูจน์ตัวตนผู้ใช้

  • เส้นทาง / login ตรวจสอบว่าพบรายการที่ตรงกันในฐานข้อมูลหรือไม่สำหรับข้อมูลประจำตัวที่ผู้ใช้ให้มา

  • หากข้อมูลรับรองไม่ถูกต้องข้อยกเว้น HTTP 401 จะถูกส่งกลับไปยังผู้ใช้

  • หากข้อมูลรับรองถูกต้องเซิร์ฟเวอร์จะสร้างโทเค็น โทเค็นนี้ถูกส่งเป็นส่วนหนึ่งของการตอบกลับไปยังผู้ใช้ สิ่งนี้ทำได้โดยฟังก์ชัน 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});
});

สำหรับทุกคำขอฟังก์ชัน app.use () จะถูกเรียกใช้ สิ่งนี้จะเรียกใช้มิดเดิลแวร์ expressJWT มิดเดิลแวร์นี้จะถอดรหัส JSON Web Token รหัสผู้ใช้ที่จัดเก็บในโทเค็นจะถูกเรียกและเก็บเป็นผู้ใช้คุณสมบัติในออบเจ็กต์คำขอ

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

เพื่อให้คุณสมบัติผู้ใช้พร้อมใช้งานภายในบริบท GraphQL คุณสมบัตินี้ถูกกำหนดให้กับ context วัตถุดังแสดงด้านล่าง -

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

สร้าง server.js ในเส้นทางโฟลเดอร์ปัจจุบัน ไฟล์ server.js ที่สมบูรณ์มีดังนี้ -

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}`));

ขั้นตอนที่ 5 - เรียกใช้แอปพลิเคชัน

ดำเนินการคำสั่ง  npm start ในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ที่นี่เราใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และพิมพ์ URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   greetingWithAuth
}

ในการตอบกลับด้านล่างเราได้รับข้อผิดพลาดเนื่องจากเราไม่ใช่ผู้ใช้ที่ตรวจสอบสิทธิ์

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

ในส่วนถัดไปให้เราสร้างแอปพลิเคชันไคลเอนต์เพื่อตรวจสอบสิทธิ์

การตั้งค่าไคลเอ็นต์ JQuery

ในแอปพลิเคชันไคลเอนต์จะมีปุ่มทักทายซึ่งจะเรียกใช้สคีมา greetingWithAuth. หากคุณคลิกปุ่มโดยไม่ต้องเข้าสู่ระบบจะมีข้อความแสดงข้อผิดพลาดดังนี้ -

เมื่อคุณเข้าสู่ระบบด้วยผู้ใช้ที่มีอยู่ในฐานข้อมูลหน้าจอต่อไปนี้จะปรากฏขึ้น -

ในการเข้าถึง greetingเราต้องเข้าถึง URL ก่อน http://localhost:9000/login เส้นทางดังต่อไปนี้

การตอบกลับจะมีโทเค็นที่สร้างจากเซิร์ฟเวอร์

$.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')
})

หลังจากล็อกอินสำเร็จเราสามารถเข้าถึงสคีมาgreetingWithAuthตามที่ระบุด้านล่าง ควรมี Authorizationheader สำหรับคำขอที่ตามมาทั้งหมดพร้อมโทเค็นผู้ถือ

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

ต่อไปนี้เป็นรหัสสำหรับ 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>

การแคชเป็นกระบวนการจัดเก็บข้อมูลในพื้นที่จัดเก็บชั่วคราวที่เรียกว่า cache. เมื่อคุณกลับไปที่หน้าที่คุณเพิ่งเยี่ยมชมเบราว์เซอร์จะรับไฟล์เหล่านั้นจากแคชแทนที่จะเป็นเซิร์ฟเวอร์ดั้งเดิม ซึ่งจะช่วยประหยัดเวลาและเครือข่ายของคุณจากภาระการรับส่งข้อมูลเพิ่มเติม

แอปพลิเคชันไคลเอนต์ที่โต้ตอบกับ GraphQL มีหน้าที่ในการแคชข้อมูลในตอนท้าย รูปแบบหนึ่งที่เป็นไปได้สำหรับสิ่งนี้คือการจองฟิลด์เช่น id เพื่อเป็นตัวระบุที่ไม่ซ้ำกันทั่วโลก

แคช InMemory

InMemoryCache เป็นที่เก็บข้อมูลปกติที่ใช้กันทั่วไปในแอปพลิเคชันไคลเอนต์ GraphQL โดยไม่ต้องใช้ไลบรารีอื่นเช่น Redux

โค้ดตัวอย่างเพื่อใช้ InMemoryCache กับ ApolloClient ได้รับด้านล่าง -

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

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

ตัวสร้าง InMemoryCache ใช้อ็อบเจ็กต์ config ที่เป็นทางเลือกพร้อมคุณสมบัติเพื่อปรับแต่งแคชของคุณ

ซีเนียร์ พารามิเตอร์และคำอธิบาย
1

addTypename

บูลีนเพื่อกำหนดว่าจะเพิ่ม __typename ลงในเอกสารหรือไม่ (ค่าเริ่มต้น: true)

2

dataIdFromObject

ฟังก์ชันที่รับอ็อบเจ็กต์ข้อมูลและส่งคืนตัวระบุเฉพาะที่จะใช้เมื่อทำให้ข้อมูลในที่จัดเก็บเป็นปกติ

3

fragmentMatcher

โดยค่าเริ่มต้น InMemoryCache จะใช้ตัวจับคู่ส่วนฮิวริสติก

4

cacheRedirects

แผนผังของฟังก์ชันเพื่อเปลี่ยนเส้นทางคิวรีไปยังรายการอื่นในแคชก่อนที่คำขอจะเกิดขึ้น

ภาพประกอบ

เราจะสร้างแอปพลิเคชันหน้าเดียวใน ReactJS โดยมีสองแท็บ - หนึ่งแท็บสำหรับหน้าแรกและอีกแท็บสำหรับนักเรียน แท็บนักเรียนจะโหลดข้อมูลจากเซิร์ฟเวอร์ GraphQL API แอปพลิเคชันจะสอบถามข้อมูลนักเรียนเมื่อผู้ใช้นำทางจากแท็บหน้าแรกไปยังแท็บนักเรียน ข้อมูลผลลัพธ์จะถูกแคชโดยแอปพลิเคชัน

นอกจากนี้เรายังจะสอบถามเวลาเซิร์ฟเวอร์โดยใช้ getTimeเพื่อตรวจสอบว่าเพจถูกแคชหรือไม่ หากมีการส่งคืนข้อมูลจากแคชเพจจะแสดงเวลาของคำขอแรกที่ส่งไปยังเซิร์ฟเวอร์ หากข้อมูลเป็นผลมาจากการร้องขอใหม่ที่ส่งไปยังเซิร์ฟเวอร์ข้อมูลนั้นจะแสดงเวลาล่าสุดจากเซิร์ฟเวอร์เสมอ

การตั้งค่าเซิร์ฟเวอร์

ต่อไปนี้เป็นขั้นตอนในการตั้งค่าเซิร์ฟเวอร์ -

ขั้นตอนที่ 1 - ดาวน์โหลดและติดตั้งการอ้างอิงที่จำเป็นสำหรับโครงการ

สร้างโฟลเดอร์ cache-server-app. เปลี่ยนไดเร็กทอรีของคุณเป็น cache-server-app จากขั้ว ทำตามขั้นตอนที่ 3 ถึง 5 ที่อธิบายไว้ในบทการตั้งค่าสภาพแวดล้อม

ขั้นตอนที่ 2 - สร้างสคีมา

เพิ่ม schema.graphql ไฟล์ในโฟลเดอร์โครงการ cache-server-app และเพิ่มรหัสต่อไปนี้ -

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

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

ขั้นตอนที่ 3 - เพิ่มตัวแก้ไข

สร้างไฟล์ resolvers.js ในโฟลเดอร์โครงการและเพิ่มรหัสต่อไปนี้ -

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}

ขั้นตอนที่ 4 - เรียกใช้แอปพลิเคชัน

สร้างไฟล์ server.js อ้างถึงขั้นตอนที่ 8 ในบทการตั้งค่าสภาพแวดล้อม ดำเนินการคำสั่งnpm startในเทอร์มินัล เซิร์ฟเวอร์จะทำงานบนพอร์ต 9000 ในที่นี้เราจะใช้ GraphiQL เป็นไคลเอนต์เพื่อทดสอบแอปพลิเคชัน

เปิดเบราว์เซอร์และป้อน URL http://localhost:9000/graphiql. พิมพ์คำค้นหาต่อไปนี้ในตัวแก้ไข -

{
   getTime
   students {
      id
      firstName
   }
}

ตัวอย่างการตอบสนองแสดงชื่อนักเรียนและเวลาเซิร์ฟเวอร์

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

การตั้งค่าไคลเอนต์ ReactJS

เปิดเทอร์มินัลใหม่สำหรับไคลเอนต์ ควรให้เทอร์มินัลเซิร์ฟเวอร์ทำงานต่อไปก่อนที่จะเรียกใช้ไคลเอนต์ แอปพลิเคชัน React จะทำงานบนพอร์ตหมายเลข 3000 และแอปพลิเคชันเซิร์ฟเวอร์บนพอร์ตหมายเลข 9000

ขั้นตอนที่ 1 - สร้างแอปพลิเคชันตอบสนอง

ในไคลเอนต์เทอร์มินัลพิมพ์คำสั่งต่อไปนี้ -

npx create-react-app hello-world-client

สิ่งนี้จะติดตั้งทุกสิ่งที่จำเป็นสำหรับแอปพลิเคชันการตอบสนองทั่วไป npx utility และ create-react-appเครื่องมือสร้างโครงการที่มีชื่อสวัสดีลูกค้าทั่วโลก เมื่อการติดตั้งเสร็จสิ้นให้เปิดโครงการใน VSCode

ติดตั้งโมดูลเราเตอร์เพื่อตอบสนองโดยใช้คำสั่งต่อไปนี้ - npm install react-router-dom.

ขั้นตอนที่ 2 - เริ่มสวัสดีลูกค้าทั่วโลก

เปลี่ยนเส้นทางโฟลเดอร์ปัจจุบันในเทอร์มินัลเป็น hello-world-client พิมพ์ npm start เพื่อเปิดตัวโปรเจ็กต์ การดำเนินการนี้จะเรียกใช้เซิร์ฟเวอร์การพัฒนาที่พอร์ต 3000 และจะเปิดเบราว์เซอร์โดยอัตโนมัติและโหลดหน้าดัชนี

สิ่งนี้แสดงในภาพหน้าจอด้านล่าง -

ขั้นตอนที่ 3 - ติดตั้ง Apollo Client Libraries

ในการติดตั้ง Apollo Client ให้เปิดเทอร์มินัลใหม่และอยู่ในเส้นทางโฟลเดอร์โครงการปัจจุบัน พิมพ์คำสั่งต่อไปนี้ -

npm install apollo-boost graphql

สิ่งนี้จะดาวน์โหลดไลบรารี graphql สำหรับฝั่งไคลเอ็นต์และแพ็คเกจ Apollo Boost เราสามารถยืนยันสิ่งนี้ได้โดยพิมพ์ npm view apollo-boost dependencies สิ่งนี้จะมีการอ้างอิงมากมายดังที่แสดงด้านล่าง -

{ 
   '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' 
}

เราจะเห็นได้ชัดเจนว่ามีการติดตั้งไลบรารี apollo-client

ขั้นตอนที่ 4 - แก้ไขส่วนประกอบแอพในไฟล์ index.js

สำหรับแอปพลิเคชันตอบสนองแบบง่ายคุณจะต้องเก็บไฟล์ index.js ใน src โฟลเดอร์และ index.htmlในโฟลเดอร์สาธารณะ ไฟล์อื่น ๆ ทั้งหมดที่สร้างขึ้นโดยอัตโนมัติสามารถลบออกได้

โครงสร้างไดเร็กทอรีได้รับด้านล่าง -

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

เพิ่มไฟล์เพิ่มเติม students.js ซึ่งจะมีส่วนประกอบของนักเรียน รายละเอียดของนักเรียนจะดึงมาจากส่วนประกอบของนักเรียน ในส่วนประกอบของแอปเรากำลังใช้ HashRouter

ต่อไปนี้คือไฟล์ index.js ในแอปพลิเคชันตอบสนอง -

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"))

ขั้นตอนที่ 5 - แก้ไขส่วนประกอบนักเรียนใน Students.js

ในส่วนของนักเรียนเราจะใช้สองวิธีต่อไปนี้ในการโหลดข้อมูล -

  • Fetch API (loadStudents_noCache) - สิ่งนี้จะเรียกคำขอใหม่ทุกครั้งที่คลิกแท็บนักเรียน

  • Apollo Client (loadWithApolloclient) - จะดึงข้อมูลจากแคช

เพิ่มฟังก์ชัน loadWithApolloclientซึ่งคำถามสำหรับนักเรียนและเวลาจากเซิร์ฟเวอร์ ฟังก์ชันนี้จะเปิดใช้งานการแคช ที่นี่เราใช้ฟังก์ชัน gql เพื่อแยกวิเคราะห์แบบสอบถาม

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

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

Fetch APIเป็นอินเทอร์เฟซที่เรียบง่ายสำหรับการดึงทรัพยากร Fetch ช่วยให้สร้างคำขอทางเว็บและจัดการการตอบสนองได้ง่ายกว่า XMLHttpRequest รุ่นเก่า วิธีต่อไปนี้แสดงการโหลดข้อมูลโดยตรงโดยใช้ fetch api -

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;
}

ในตัวสร้างของ StudentsComponent เรียกไฟล์ loadWithApolloClientวิธี. ที่สมบูรณ์ Student.js ไฟล์อยู่ด้านล่าง -

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

ขั้นตอนที่ 6 - เรียกใช้ React Application ด้วยการเริ่ม npm

คุณสามารถทดสอบแอปพลิเคชันตอบกลับได้โดยเปลี่ยนจากแท็บหน้าแรกเป็นแท็บนักเรียน เมื่อแท็บนักเรียนโหลดด้วยข้อมูลจากเซิร์ฟเวอร์ มันจะแคชข้อมูล คุณสามารถทดสอบได้โดยเปลี่ยนแท็บจากที่บ้านเป็นแท็บนักเรียนหลาย ๆ ครั้ง ผลลัพธ์จะเป็นดังที่แสดงด้านล่าง -

หากคุณโหลดหน้านักเรียนก่อนโดยพิมพ์ URL http://localhost:3000/#/studentsคุณจะเห็นได้ว่าเวลาในการโหลดแอปตอบกลับและ GraphQL จะเท่ากันโดยประมาณ หลังจากนั้นหากคุณเปลี่ยนเป็นมุมมองหน้าแรกและกลับไปที่เซิร์ฟเวอร์ GraphQL เวลาจะไม่เปลี่ยนแปลง นี่แสดงว่าข้อมูลถูกแคช

ขั้นตอนที่ 7 - เปลี่ยนการเรียก loadWithApolloclient เป็น loadStudents_noCache

หากคุณเปลี่ยนวิธีการโหลดเป็น loadStudents_noCacheในตัวสร้าง StudentComponent ผลลัพธ์จะไม่แคชข้อมูล สิ่งนี้แสดงให้เห็นความแตกต่างระหว่างการแคชและการไม่แคช

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

จากผลลัพธ์ข้างต้นเป็นที่ชัดเจนว่าหากคุณสลับไปมาระหว่างแท็บเวลาจากเซิร์ฟเวอร์ graphql จะเป็นเวลาล่าสุดเสมอซึ่งหมายความว่าข้อมูลจะไม่ถูกแคช