fix: like button race condition
This commit is contained in:
@@ -5,6 +5,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const slug = likeIcon.dataset.slug;
|
||||
const likeCountSpan = document.querySelector(`[data-like-count][data-slug="${slug}"]`);
|
||||
const storageKey = `liked-${slug}`;
|
||||
let isRequestInProgress = false;
|
||||
|
||||
// Function to update the UI based on liked state and count
|
||||
const updateUI = (isLiked, count) => {
|
||||
@@ -48,6 +49,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// Add click event listener to the icon
|
||||
likeIcon.addEventListener('click', async () => {
|
||||
// If a request is already in progress, do nothing.
|
||||
if (isRequestInProgress) {
|
||||
return;
|
||||
}
|
||||
isRequestInProgress = true;
|
||||
|
||||
// Stop the hint animation if it's running
|
||||
likeIcon.classList.remove('hint-animation');
|
||||
// Toggle the liked state
|
||||
@@ -56,7 +63,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/likes/${slug}`, { method });
|
||||
if (!response.ok) return;
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server responded with ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
const isNowLiked = !isCurrentlyLiked;
|
||||
@@ -67,6 +76,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error submitting like/unlike:', error);
|
||||
} finally {
|
||||
isRequestInProgress = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -3,10 +3,15 @@ const cors = require('cors');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const rateLimit = require('express-rate-limit');
|
||||
const { Mutex } = require('async-mutex');
|
||||
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
// Create mutexes to prevent race conditions when updating JSON files
|
||||
const viewsMutex = new Mutex();
|
||||
const likesMutex = new Mutex();
|
||||
|
||||
// trust proxy:
|
||||
// Used by express-rate-limit to obtain the client's IP address.
|
||||
// '1' means that the first hop (your reverse proxy) is trusted.
|
||||
@@ -97,6 +102,7 @@ app.get('/api/likes/:slug', validateSlug, async (req, res) => {
|
||||
|
||||
// POST: Increment the view count for a specific post slug
|
||||
app.post('/api/views/:slug', validateSlug, async (req, res) => {
|
||||
const release = await viewsMutex.acquire();
|
||||
try {
|
||||
const { slug } = req.params;
|
||||
const views = await fs.readJson(dbPath);
|
||||
@@ -106,11 +112,14 @@ app.post('/api/views/:slug', validateSlug, async (req, res) => {
|
||||
} catch (error) {
|
||||
console.error('Error updating view count:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
});
|
||||
|
||||
// POST: Increment the like count for a specific post slug
|
||||
app.post('/api/likes/:slug', validateSlug, async (req, res) => {
|
||||
const release = await likesMutex.acquire();
|
||||
try {
|
||||
const { slug } = req.params;
|
||||
const likes = await fs.readJson(likesDbPath);
|
||||
@@ -120,11 +129,14 @@ app.post('/api/likes/:slug', validateSlug, async (req, res) => {
|
||||
} catch (error) {
|
||||
console.error('Error updating like count:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE: Decrement the like count for a specific post slug (unlike)
|
||||
app.delete('/api/likes/:slug', validateSlug, async (req, res) => {
|
||||
const release = await likesMutex.acquire();
|
||||
try {
|
||||
const { slug } = req.params;
|
||||
const likes = await fs.readJson(likesDbPath);
|
||||
@@ -139,6 +151,8 @@ app.delete('/api/likes/:slug', validateSlug, async (req, res) => {
|
||||
} catch (error) {
|
||||
console.error('Error updating like count:', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user