स्पोइलर: मैं वर्तमान में विकसित कर रहा हूं कि ओपन-सोर्स चैट एप्लिकेशन क्या होगा।
आप मिडलवेयर से कार्यों को अलग करके और सॉकेट क्लाइंट को मिडलवेयर से अलग करके बेहतर कर सकते हैं। इसलिए, कुछ इस तरह है, जिसके परिणामस्वरूप:
- प्रकार -> अनुरोध, सफलता, असफलता प्रकार प्रत्येक अनुरोध (अनिवार्य नहीं) के लिए।
- प्रसारण -> स्टोर करने के लिए अलग-अलग राज्यों
- क्रिया -> कनेक्ट करने के लिए/डिस्कनेक्ट/फेंकना/सुनने कार्यों भेजें।
- मिडिलवेयर -> सॉकेट क्लाइंट (socket.io) - अपने कार्यों का इलाज, और सॉकेट ग्राहक
- ग्राहक के पास है या नहीं वर्तमान कार्रवाई करने के लिए>।
कोड के नीचे विकास किया जा रहा है जो वास्तविक एप्लिकेशन से लिया जाता है (कभी कभी कुछ संपादित), और वे स्थितियों के बहुमत के लिए पर्याप्त हैं, लेकिन SocketClient जैसे कुछ सामान 100% पूर्ण नहीं हो सकता है।
क्रिया
आप कार्रवाई संभव के रूप में सरल किया जा करना चाहते हैं, क्योंकि वे अक्सर काम दोहराया जाता है और आप शायद उनमें से बहुत सारे होने पहुंच जाएंगे।
export function send(chatId, content) {
const message = { chatId, content };
return {
type: 'socket',
types: [SEND, SEND_SUCCESS, SEND_FAIL],
promise: (socket) => socket.emit('SendMessage', message),
}
}
सूचना सॉकेट एक parametrized समारोह, इस तरह से हम पूरे आवेदन भर एक ही सॉकेट उदाहरण साझा कर सकते हैं और हम किसी भी आयात के बारे में जो भी चिंता करने की ज़रूरत नहीं है (हम कैसे इसे बाद में करना दिखाता हूँ)।
मिडिलवेयर (socketMiddleware.js):
हम erikras/react-redux-universal-hot-example का उपयोग करता है के रूप में एक समान रणनीति का उपयोग करेंगे, हालांकि AJAX के बजाय सॉकेट के लिए।
हमारे सॉकेट मिडलवेयर केवल सॉकेट अनुरोधों को संसाधित करने के लिए जिम्मेदार होंगे।
मिडिलवेयर सॉकेट क्लाइंट पर कार्रवाई गुजरता है, और डिस्पैच:
- अनुरोध (कार्रवाई
types[0]
): अनुरोध कर रहा है (action.type
कम करने के लिए भेजा जाता है)।
- सफलता (कार्रवाई
types[1]
): अनुरोध सफलता पर (action.type
और action.result
के रूप में सर्वर प्रतिक्रिया reducer को भेजी जाती है)।
- विफलता (कार्रवाई
types[2]
): अनुरोध विफलता पर (action.type
और action.error
के रूप में सर्वर प्रतिक्रिया reducer को भेजी जाती है)।
export default function socketMiddleware(socket) {
// Socket param is the client. We'll show how to set this up later.
return ({dispatch, getState}) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
/*
* Socket middleware usage.
* promise: (socket) => socket.emit('MESSAGE', 'hello world!')
* type: always 'socket'
* types: [REQUEST, SUCCESS, FAILURE]
*/
const { promise, type, types, ...rest } = action;
if (type !== 'socket' || !promise) {
// Move on! Not a socket request or a badly formed one.
return next(action);
}
const [REQUEST, SUCCESS, FAILURE] = types;
next({...rest, type: REQUEST});
return promise(socket)
.then((result) => {
return next({...rest, result, type: SUCCESS });
})
.catch((error) => {
return next({...rest, error, type: FAILURE });
})
};
}
SocketClient.js
केवल एक ही है कि कभी लोड और socket.io-ग्राहक का प्रबंधन करेगा।
[वैकल्पिक] (कोड में नीचे 1 देखें)। socket.io के बारे में एक बहुत ही रोचक विशेषता यह तथ्य है कि आपके पास message acknowledgements हो सकता है, जो एक HTTP अनुरोध करते समय सामान्य जवाब होगा। हम यह सत्यापित करने के लिए उनका उपयोग कर सकते हैं कि प्रत्येक अनुरोध सही था। ध्यान दें कि इस सुविधा का उपयोग करने के लिए सर्वर socket.io आदेशों को भी यह नवीनतम पावती पैरामीटर होना चाहिए।
import io from 'socket.io-client';
// Example conf. You can move this to your config file.
const host = 'http://localhost:3000';
const socketPath = '/api/socket.io';
export default class socketAPI {
socket;
connect() {
this.socket = io.connect(host, { path: socketPath });
return new Promise((resolve, reject) => {
this.socket.on('connect',() => resolve());
this.socket.on('connect_error', (error) => reject(error));
});
}
disconnect() {
return new Promise((resolve) => {
this.socket.disconnect(() => {
this.socket = null;
resolve();
});
});
}
emit(event, data) {
return new Promise((resolve, reject) => {
if (!this.socket) return reject('No socket connection.');
return this.socket.emit(event, data, (response) => {
// Response is the optional callback that you can use with socket.io in every request. See 1 above.
if (response.error) {
console.error(response.error);
return reject(response.error);
}
return resolve();
});
});
}
on(event, fun) {
// No promise is needed here, but we're expecting one in the middleware.
return new Promise((resolve, reject) => {
if (!this.socket) return reject('No socket connection.');
this.socket.on(event, fun);
resolve();
});
}
}
app.js
हमारे एप्लिकेशन स्टार्ट-अप पर, हम SocketClient
प्रारंभ और यह दुकान विन्यास को गुजरती हैं। हमारे नए प्रारंभ दुकान middlewares (उस पैरामीटर जो हम तुमसे कहा था हम बाद में समझा जाएगा याद है?) के लिए SocketClient
const socketClient = new SocketClient();
const store = configureStore(initialState, socketClient, apiClient);
configureStore.js
हम साथ socketMiddleware
जोड़ें।
export default function configureStore(initialState, socketClient, apiClient) {
const loggerMiddleware = createLogger();
const middleware = [
...
socketMiddleware(socketClient),
...
];
[कुछ भी नहीं विशेष] कार्रवाई प्रकार स्थिरांक
कुछ भी नहीं विशेष = आप सामान्य रूप से क्या करेंगे।
const SEND = 'redux/message/SEND';
const SEND_SUCCESS = 'redux/message/SEND_SUCCESS';
const SEND_FAIL = 'redux/message/SEND_FAIL';
[कुछ भी नहीं विशेष] प्रसारण
export default function reducer(state = {}, action = {}) {
switch(action.type) {
case SEND: {
return {
...state,
isSending: true,
};
}
default: {
return state;
}
}
}
यह बहुत काम की तरह लग सकता है, लेकिन एक बार आप यह निर्धारित किया है ऊपर यह इसके लायक है। आपका प्रासंगिक कोड पढ़ने, डीबग करना आसान होगा और आप गलतियों को कम करने के लिए कम प्रवण होंगे।
पीएस: आप AJAX API कॉल के साथ भी इस रणनीति का अनुसरण कर सकते हैं।
सामान्य रूप से इस प्रकार का प्रश्न स्टैक ओवरफ्लो के लिए उपयुक्त नहीं है, लेकिन हां, आपका दृष्टिकोण उचित दिखता है। केवल एक चीज जो मुझे "अजीब" के रूप में कूदती है केवल सशर्त रूप से 'अगली (कार्रवाई)' कहती है। आम तौर पर आप अगले मिडलवेयर (प्रेषक) को कॉल करना चाहते हैं, उदा। इसे लॉगिंग या किसी और चीज को संभालने के लिए जो आपके पास हो सकता है। – WTK
यह काफी उचित दिखता है, लेकिन मैं वास्तव में रेडक्स-सागा मिडलवेयर में एक नज़र डालने की सिफारिश करता हूं, जो आपको एक विशिष्ट कार्रवाई '''' ले लेगा और इसके लिए जनरेटर को स्पिन करेगा। वहां से आप अधिक उन्नत तर्क स्थापित कर सकते हैं, जैसे कि एकाधिक चैनल, सदस्यता समाप्त, इत्यादि :) – horyd
@WTK अगले मिडलवेयर को कॉल करने के संबंध में, क्या मैं अगले मध्यवर्ती को भेजने के लिए एक और शर्त जोड़ूंगा? – Ganbel