في هذا المنشور، ستتعلم كيفية تنفيذ الإشعارات الفورية باستخدام JavaScript باتباع أفضل الممارسات على مستوى الإنتاج. أحد أفضل الأشياء هو أنني سأوفر لك بنية مجلد أيضًا، بحيث يمكنك إعداد مشروعك بسهولة.
يحتاج إعداد الإشعارات الفورية في تطبيق حقيقي إلى تخطيط دقيق. سأوضح لك كيفية إنشاء هذه الميزة في تطبيق Node.js الاحترافي. سنغطي أجزاء مهمة مثل كيفية تنظيم التعليمات البرمجية الخاصة بك، والحفاظ على أمان الأشياء، والتأكد من أنها تعمل بشكل جيد حتى مع نمو تطبيقك.
للبدء، أنت بحاجة إلى مكتبة لمساعدتك في إرسال الإشعارات من خادم Node.js الخاص بك. توفر مكتبة الدفع على الويب أدوات لإرسال الإشعارات وإدارة المفاتيح الضرورية.
أولاً، لنقم بإعداد هيكل المشروع للحفاظ على قاعدة تعليمات برمجية نظيفة وقابلة للتطوير:
/notification-service ├── /config │ ├── default.js │ └── production.js ├── /controllers │ └── notificationController.js ├── /models │ └── user.js ├── /routes │ └── notificationRoutes.js ├── /services │ ├── notificationService.js │ ├── subscriptionService.js │ └── webPushService.js ├── /utils │ └── errorHandler.js ├── /tests │ └── notification.test.js ├── app.js ├── package.json ├── .env └── README.md
قبل الغوص في التنفيذ، تأكد من تثبيت حزم NPM التالية:
bash npm install express mongoose web-push dotenv supertest
إنشاء ملفات تكوين لبيئات مختلفة (مثل التطوير والإنتاج). تقوم هذه الملفات بتخزين إعدادات خاصة بالبيئة.
// /config/default.js module.exports = { server: { port: 3000, env: 'development' }, pushNotifications: { publicVapidKey: process.env.VAPID_PUBLIC_KEY, privateVapidKey: process.env.VAPID_PRIVATE_KEY, gcmApiKey: process.env.GCM_API_KEY }, db: { uri: process.env.MONGO_URI } };
// /config/production.js module.exports = { server: { port: process.env.PORT || 3000, env: 'production' }, // Same structure as default, with production-specific values };
استخدم Mongoose لتحديد مخطط المستخدم واشتراكات الإشعارات.
// /models/user.js const mongoose = require('mongoose'); const subscriptionSchema = new mongoose.Schema({ endpoint: String, keys: { p256dh: String, auth: String } }); const userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, subscriptions: [subscriptionSchema], preferences: { pushNotifications: { type: Boolean, default: true } } }); module.exports = mongoose.model('User', userSchema);
وحدة منطق التعامل مع الإشعارات في الخدمات.
// /services/webPushService.js const webPush = require('web-push'); const config = require('config'); webPush.setVapidDetails( 'mailto:[email protected]', config.get('pushNotifications.publicVapidKey'), config.get('pushNotifications.privateVapidKey') ); module.exports = { sendNotification: async (subscription, payload) => { try { await webPush.sendNotification(subscription, JSON.stringify(payload)); } catch (error) { console.error('Error sending notification', error); } } };
// /services/notificationService.js const User = require('../models/user'); const webPushService = require('./webPushService'); module.exports = { sendPushNotifications: async (userId, payload) => { const user = await User.findById(userId); if (user && user.preferences.pushNotifications) { user.subscriptions.forEach(subscription => { webPushService.sendNotification(subscription, payload); }); } } };
التعامل مع مسارات واجهة برمجة التطبيقات ودمج الخدمات.
// /controllers/notificationController.js const notificationService = require('../services/notificationService'); exports.sendNotification = async (req, res, next) => { try { const { userId, title, body } = req.body; const payload = { title, body }; await notificationService.sendPushNotifications(userId, payload); res.status(200).json({ message: 'Notification sent successfully' }); } catch (error) { next(error); } };
إعداد المسارات لواجهة برمجة التطبيقات (API) الخاصة بك.
// /routes/notificationRoutes.js const express = require('express'); const router = express.Router(); const notificationController = require('../controllers/notificationController'); router.post('/send', notificationController.sendNotification); module.exports = router;
مركزية معالجة الأخطاء لضمان عدم تعطل التطبيق.
// /utils/errorHandler.js module.exports = (err, req, res, next) => { console.error(err.stack); res.status(500).send({ error: 'Something went wrong!' }); };
تهيئة التطبيق والاتصال بقاعدة البيانات.
// app.js const express = require('express'); const mongoose = require('mongoose'); const config = require('config'); const notificationRoutes = require('./routes/notificationRoutes'); const errorHandler = require('./utils/errorHandler'); const app = express(); app.use(express.json()); app.use('/api/notifications', notificationRoutes); app.use(errorHandler); mongoose.connect(config.get('db.uri'), { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log('MongoDB connected...')) .catch(err => console.error('MongoDB connection error:', err)); const PORT = config.get('server.port'); app.listen(PORT, () => console.log(`Server running in ${config.get('server.env')} mode on port ${PORT}`));
اكتب الاختبارات للتأكد من أن خدمتك تعمل كما هو متوقع في ظل ظروف مختلفة.
// /tests/notification.test.js const request = require('supertest'); const app = require('../app'); describe('Notification API', () => { it('should send a notification', async () => { const res = await request(app) .post('/api/notifications/send') .send({ userId: 'someUserId', title: 'Test', body: 'This is a test' }); expect(res.statusCode).toEqual(200); expect(res.body.message).toBe('Notification sent successfully'); }); });
يضمن هذا الإعداد على مستوى الإنتاج أن نظام الإشعارات الفورية الخاص بك قابل للتطوير وآمن وقابل للصيانة. تم تنظيم الكود لدعم سهولة الاختبار والنشر والمراقبة، باتباع أفضل ممارسات الصناعة. إذا كان لديك أي أسئلة أخرى أو كنت بحاجة إلى تفاصيل تنفيذ محددة، فلا تتردد في طرحها!
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3