में Node.js setTimeout के रिटर्न मान भंडारण मैं Node.js में setTimeout
उपयोग कर रहा हूँ और उस में यह संख्या की जगह एक वस्तु देता है कि क्लाइंट-साइड setTimeout
से अलग तरीके से व्यवहार करने लगता है। मैं इसे रेडिस में स्टोर करना चाहता हूं, लेकिन चूंकि रेडिस केवल तारों को स्टोर करता है, इसलिए मुझे ऑब्जेक्ट को स्ट्रिंग में बदलने की ज़रूरत है। हालांकि, JSON.stringify
का उपयोग करके एक परिपत्र संदर्भ त्रुटि फेंकता है। अगर मैं इसे रेडिस से लाने में सक्षम होना चाहता हूं और clearTimeout
पर कॉल करना चाहता हूं तो मैं इस ऑब्जेक्ट को रेडिस में कैसे स्टोर कर सकता हूं?redis
redis
उत्तर
आप ऑब्जेक्ट को रेडिस में स्टोर नहीं कर सकते हैं। setTimeout
विधि एक हैंडलर (ऑब्जेक्ट संदर्भ) देता है।
एक विचार स्मृति में अपना स्वयं का सहयोगी सरणी बनाना होगा, और इंडेक्स को रेडिस में स्टोर करना होगा। उदाहरण के लिए:
var nextTimerIndex = 0;
var timerMap = {};
var timer = setTimeout(function(timerIndex) {
console.log('Ding!');
// Free timer reference!
delete timerMap[timerIndex];
}, 5 * 1000, nextTimerIndex);
// Store index in Redis...
// Then, store the timer object for later reference
timerMap[nextTimerIndex++] = timer;
// ...
// To clear the timeout
clearTimeout(timerMap[myTimerIndex]);
ठीक है, लेकिन मुझे इसे Redis – user730569
से लाने के बाद ऑब्जेक्ट पर 'clearTimeout' को कॉल करने में सक्षम होना चाहिए। मैंने – legege
उदाहरण के साथ उत्तर संपादित किया है, मैं इसे उदाहरणों में साझा करने में सक्षम होना चाहता हूं ताकि स्मृति में वास्तव में कोई नहीं हो विकल्प – user730569
इस कोड को प्रयोग किया जाता है जब समय समाप्ति सर्वर के दौरान जारी रहता नहीं हो की जरूरत है पुन: प्रारंभ होता
var timeouts = {};
app.get('/', function (req, res) {
var index = timeouts.length;
timeouts[index] = setTimeout(console.log, 1000000, req.user.name);
redis.set('timeout:' + req.user.name, index, function (err, reply) {
res.end();
});
});
app.get('/clear', function (req, res) {
redis.get('timeout:' + req.user.name, function (err, index) {
clearTimeout(timeouts[index]);
delete timeouts[index];
redis.delete('timeout:' + req.user.name);
res.end();
});
});
आप समय समाप्ति की जरूरत है सर्वर पुनरारंभ के दौरान जारी रहता होने के लिए है, तो आप _idleStart
स्टोर करने के लिए आवश्यकता हो सकती है और redis में हर टाइमर के लिए _idleTimeout
मूल्यों, और उन्हें हर लोड आप सर्वर पुन: प्रारंभ होता
app.get('/', function (req, res) {
var timeout = setTimeout(console.log, 1000000, req.user.name);
var time = timeout._idleStart.getTime() + timeout._idleTimeout;
redis.set('timeout:' + req.user.name, time, function (err, reply) {
res.end();
});
});
app.get('/clear', function (req, res) {
redis.delete('timeout:' + req.user.name);
res.end();
});
// Load timeouts on server start
// *I know this is not the correct redis command*
// *It's not accurate, only approx*
redis.get('timeout:*', function (err, vals) {
vals.forEach(function (val) {
var time = val - new Date().getTime();
setTimeout(console.log, time, username)
});
});
आप टाइमर ऑब्जेक्ट संदर्भ लीक कर रहे हैं। – legege
मुझे इसे सर्वर पुनरारंभ करने में सहेजने की ज़रूरत है ... – user730569
@ user730569 यह काम नहीं करेगा ... टाइमर पुनरारंभ करने के बाद चला जाएगा। पुनरारंभ करने के बाद आपको उन्हें फिर से निर्धारित करने का एक तरीका ढूंढना होगा। आप प्रारंभ समय को जारी रख सकते हैं, और फिर से शुरू करने पर टाइमआउट मान को फिर से समझ सकते हैं। – legege
मैं क्या करने की कोशिश की गई थी ओपी के समान ही बात। मेरे समाधान मेरी डिस्कनेक्ट हैंडलर में टाइमआउट के भीतर एक नया कुंजी पर एक सशर्त चेक के साथ समय समाप्ति सेट करने के लिए किया गया था:
redis.hset("userDisconnecting:" + userId, "disconnect", 1);
setTimeout(function() {
redis.hget("userDisconnecting:" + userId, "disconnect",
function(err, result) {
if (result.toString() === "1") {
//do stuff, like notify other clients of the disconnect.
}
});
}, 10000);
तब, जब ग्राहक फिर से जोड़ता है, मैं 0
है कि कुंजी है, तो सामान की जरूरत है कि सेट सच डिस्कनेक्ट होने पर आग नहीं होता है:
redis.hset("userDisconnecting:" + userId, "disconnect", 0);
टाइमआउट खुद को सर्वर के पुनरारंभ होने के दौरान जारी रहता नहीं हैं, लेकिन अगर आप स्टार्टअप पर स्वीपर विधि बंद लात द्वारा कि हल कर सकते थे। कनेक्टेड क्लाइंट वापस "ऑनलाइन" वापस आ जाएंगे।
मुझे नहीं लगता कि 'setTimeout' कॉल में परिपत्र संदर्भ त्रुटि के साथ कुछ भी करना है। http://stackoverflow.com/questions/1493453/example-of-a-circular-reference-in-javascript – Trevor
@Trevor 'setTimeout' इस ऑब्जेक्ट को बनाता है:' {_idleTimeout: 1000000000, _idlePrev: {_idleNext: [परिपत्र ], _idlePrev: [परिपत्र], ontimeout: [समारोह]}, _idleNext: {_idleNext: [परिपत्र], _idlePrev: [परिपत्र], ontimeout: [समारोह]}, _onTimeout: [समारोह], _idleStart: सोम, 02 जुलाई 2012 20:28:18 GMT} ' – user730569
' _idleNext' और '_idlePrev' कुंजी परिपत्र संदर्भ प्रतीत होते हैं ... – user730569