Metinleri Sıralama
Coddy'nin Node.js Journey'sinin REST API'leri bölümünün bir parçası. Ders 15 / 25.
İzleyiciniz görevleri filtreleyebilir. Şimdi de depolanan sırayı değiştirmeden bir istemcinin alfabetik başlıklar istemesine izin verin. Bir sıralama karşılaştırması, ilk öğesi ikinciden önce geliyorsa negatif, sonra geliyorsa pozitif bir sayı döndürür; öğeler eşitse sıfır döndürür.
const sorted = cities.toSorted((a, b) => a.name.localeCompare(b.name));Dizeleri çıkarmak işe yarar bir sıralama sağlamaz. localeCompare metinleri karşılaştırır. toSorted yeni bir dizi döndürür ve özgün diziyi değiştirmez. Filtreleme ve sıralamanın birlikte çalışması için filtrelenmiş listeyi sıralayın. Sonraki Sıralama dersi başka alanlar, azalan sıralama ve geçersiz sorgu işlemlerini ele alır.
Görev
KolayGörev izleyicinize routes/tasks.js dosyasında devam edin. Liste rotasında, mevcut filtrelerden sonra ?sort=title görevleri başlıklarına göre alfabetik sırayla döndürsün. Bu değer olmadan mevcut davranışı koruyun. Saklanan görev sırasını değiştirmeyin.
GET /api/tasks?sort=title isteğini, ardından GET /api/tasks isteğini deneyin. İkinci liste hâlâ özgün sıralamasında olmalı. ?done=false&sort=title ile filtreleme, yalnızca tamamlanmamış görevleri döndürmeye devam etmelidir.
Kendin dene
import { Router } from 'express';
import { z } from 'zod';
import { sendError, sendInvalid } from '../errors.js';
import { nextId, tasks } from '../store.js';
const router = Router();
// PUT tarafından gönderildiği biçimiyle eksiksiz bir görev. .strict(), listelemediği alanları reddeder.
const Task = z
.object({
title: z.string().trim().min(1).max(100),
done: z.boolean(),
})
.strict();
const NewTask = Task.partial({ done: true });
const TaskChanges = Task.partial();
// Büyük-küçük harf fark etmeksizin, başka bir görev zaten bu başlığa sahipse true.
const titleTaken = (title, exceptId) =>
tasks.some((t) => t.id !== exceptId && t.title.toLowerCase() === title.toLowerCase());
router.get('/', (req, res) => {
const { done, q } = req.query;
let list = tasks;
if (done !== undefined) {
if (done !== 'true' && done !== 'false') {
return sendError(res, 400, 'invalid_query', 'done must be true or false');
}
list = list.filter((t) => t.done === (done === 'true'));
}
if (q !== undefined) {
const words = String(q).toLowerCase();
list = list.filter((t) => t.title.toLowerCase().includes(words));
}
res.json(list);
});
router.get('/:id', (req, res) => {
const task = tasks.find((t) => t.id === Number(req.params.id));
if (!task) {
return sendError(res, 404, 'not_found', 'Task not found');
}
res.json(task);
});
router.post('/', (req, res) => {
const result = NewTask.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
const { title, done = false } = result.data;
if (titleTaken(title)) {
return sendError(res, 409, 'conflict', 'A task with this title already exists');
}
const task = { id: nextId(), title, done, createdAt: new Date().toISOString() };
tasks.push(task);
res.status(201).location(`/api/tasks/${task.id}`).json(task);
});
router.patch('/:id', (req, res) => {
const task = tasks.find((t) => t.id === Number(req.params.id));
if (!task) {
return sendError(res, 404, 'not_found', 'Task not found');
}
const result = TaskChanges.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
if (result.data.title !== undefined && titleTaken(result.data.title, task.id)) {
return sendError(res, 409, 'conflict', 'A task with this title already exists');
}
Object.assign(task, result.data);
res.json(task);
});
router.put('/:id', (req, res) => {
const index = tasks.findIndex((t) => t.id === Number(req.params.id));
if (index === -1) {
return sendError(res, 404, 'not_found', 'Task not found');
}
const result = Task.safeParse(req.body);
if (!result.success) {
return sendInvalid(res, result.error);
}
const { id, createdAt } = tasks[index];
if (titleTaken(result.data.title, id)) {
return sendError(res, 409, 'conflict', 'A task with this title already exists');
}
tasks[index] = { id, ...result.data, createdAt };
res.json(tasks[index]);
});
router.delete('/:id', (req, res) => {
const index = tasks.findIndex((t) => t.id === Number(req.params.id));
if (index === -1) {
return sendError(res, 404, 'not_found', 'Task not found');
}
tasks.splice(index, 1);
res.status(204).end();
});
export default router;
REST API'leri bölümündeki tüm dersler
1Kaynaklar ve Fiiller
Kaynaklar ve URL'lerPOST ile Oluşturma4Tarayıcılar, Sürümler ve Yapılandırma
Origin NedirBaşka Bir Origin'e İzin VermeCORSAPI'yi Çağıran Bir SayfaKendi başına pratik yap: Express playground