Topic 009: Basic features in Node.js
- Instead of traditional pagination where users click through pages, infinite scroll dynamically loads content as the user scrolls down the page. It provides a seamless experience and is commonly used in applications with large datasets.
// Server-side code (assuming you have an endpoint to fetch data)
app.get("/data", (req, res) => {
const page = req.query.page || 1;
const pageSize = 10;
const start = (page - 1) * pageSize;
const end = start + pageSize;
// Fetch data from the database
YourModel.find()
.skip(start)
.limit(pageSize)
.exec((err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Allows users to narrow down data based on specific criteria, such as date range, category, or keyword. Filtering helps users find relevant information quickly.
app.get("/data", (req, res) => {
const { category, keyword } = req.query;
let query = {};
if (category) {
query.category = category;
}
if (keyword) {
query.$or = [
{ name: { $regex: keyword, $options: "i" } },
{ description: { $regex: keyword, $options: "i" } },
];
}
YourModel.find(query, (err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Enables users to reorder data based on different attributes, such as date, alphabetical order, or numerical value. Sorting enhances usability by allowing users to arrange data in a way that suits their needs.
app.get("/data", (req, res) => {
const { sortBy } = req.query;
YourModel.find()
.sort(sortBy)
.exec((err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Provides users with the ability to search for specific keywords or phrases within the dataset. Search functionality helps users locate information efficiently, especially in large datasets.
app.get("/data", (req, res) => {
const { searchQuery } = req.query;
YourModel.find({ $text: { $search: searchQuery } }, (err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Integrating charts, graphs, or other visual representations of data can help users understand complex information more easily. Data visualization tools like D3.js or Chart.js are commonly used for this purpose.
// Assuming you have an endpoint to fetch data for visualization
app.get("/visualization-data", (req, res) => {
// Fetch data from the database
YourModel.find({}, (err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Similar to infinite scroll, lazy loading delays the loading of non-essential content until it's needed. It can improve initial page load times and overall performance by only loading data as the user interacts with the application.
// Assuming you have an endpoint to fetch data for lazy loading
app.get("/lazy-load-data", (req, res) => {
const { startIndex, count } = req.query;
YourModel.find()
.skip(startIndex)
.limit(count)
.exec((err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- Storing frequently accessed data in a cache can improve application performance by reducing the need to fetch data from the server repeatedly.
Caching is often implemented using external libraries like Redis or Memcached. Here's a simplified example using in-memory caching:
const cache = {};
app.get("/cached-data", (req, res) => {
const cacheKey = req.query.cacheKey;
if (cache[cacheKey]) {
return res.json(cache[cacheKey]);
}
YourModel.find({}, (err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
cache[cacheKey] = data;
res.json(data);
});
});- Implementing real-time functionality using technologies like WebSockets or Server-Sent Events allows users to receive instant updates as data changes. This is particularly useful in collaborative applications or those where data changes frequently.
const http = require("http");
const server = http.createServer(app);
const io = require("socket.io")(server);
io.on("connection", (socket) => {
console.log("A user connected");
// Listen for data updates
YourModel.watch().on("change", (data) => {
socket.emit("dataUpdate", data);
});
socket.on("disconnect", () => {
console.log("User disconnected");
});
});
server.listen(3000, () => {
console.log("Server is running on port 3000");
});- Instead of relying solely on page numbers, cursor-based navigation uses a unique identifier (such as an ID or timestamp) to paginate through data. This approach can be more efficient, especially with large datasets that are frequently updated.
app.get("/data", (req, res) => {
const { cursor } = req.query;
const limit = 10;
let query = {};
if (cursor) {
query._id = { $gt: cursor };
}
YourModel.find(query)
.limit(limit)
.exec((err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
res.json(data);
});
});- For tasks that involve processing large amounts of data, batch processing divides the workload into smaller chunks or batches to improve efficiency. This can be useful for tasks like data imports, exports, or bulk updates.
// Assuming you have a batch processing task to perform
app.post("/batch-process", (req, res) => {
const { batchSize } = req.body;
YourModel.find({ processed: false })
.limit(batchSize)
.exec((err, data) => {
if (err) {
return res.status(500).json({ error: "Internal server error" });
}
// Perform batch processing logic here
res.json({ message: "Batch processing completed" });
});
});These are simplified examples to demonstrate the implementation of each functionality. Depending on your specific use case and requirements, you may need to adapt and expand upon these examples.