redis

2012-07-02 41 views
11

में Node.js setTimeout के रिटर्न मान भंडारण मैं Node.js में setTimeout उपयोग कर रहा हूँ और उस में यह संख्या की जगह एक वस्तु देता है कि क्लाइंट-साइड setTimeout से अलग तरीके से व्यवहार करने लगता है। मैं इसे रेडिस में स्टोर करना चाहता हूं, लेकिन चूंकि रेडिस केवल तारों को स्टोर करता है, इसलिए मुझे ऑब्जेक्ट को स्ट्रिंग में बदलने की ज़रूरत है। हालांकि, JSON.stringify का उपयोग करके एक परिपत्र संदर्भ त्रुटि फेंकता है। अगर मैं इसे रेडिस से लाने में सक्षम होना चाहता हूं और clearTimeout पर कॉल करना चाहता हूं तो मैं इस ऑब्जेक्ट को रेडिस में कैसे स्टोर कर सकता हूं?redis

+0

मुझे नहीं लगता कि 'setTimeout' कॉल में परिपत्र संदर्भ त्रुटि के साथ कुछ भी करना है। http://stackoverflow.com/questions/1493453/example-of-a-circular-reference-in-javascript – Trevor

+0

@Trevor 'setTimeout' इस ऑब्जेक्ट को बनाता है:' {_idleTimeout: 1000000000, _idlePrev: {_idleNext: [परिपत्र ], _idlePrev: [परिपत्र], ontimeout: [समारोह]}, _idleNext: {_idleNext: [परिपत्र], _idlePrev: [परिपत्र], ontimeout: [समारोह]}, _onTimeout: [समारोह], _idleStart: सोम, 02 जुलाई 2012 20:28:18 GMT} ' – user730569

+1

' _idleNext' और '_idlePrev' कुंजी परिपत्र संदर्भ प्रतीत होते हैं ... – user730569

उत्तर

1

आप ऑब्जेक्ट को रेडिस में स्टोर नहीं कर सकते हैं। 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]); 
+0

ठीक है, लेकिन मुझे इसे Redis – user730569

+0

से लाने के बाद ऑब्जेक्ट पर 'clearTimeout' को कॉल करने में सक्षम होना चाहिए। मैंने – legege

+0

उदाहरण के साथ उत्तर संपादित किया है, मैं इसे उदाहरणों में साझा करने में सक्षम होना चाहता हूं ताकि स्मृति में वास्तव में कोई नहीं हो विकल्प – user730569

0

इस कोड को प्रयोग किया जाता है जब समय समाप्ति सर्वर के दौरान जारी रहता नहीं हो की जरूरत है पुन: प्रारंभ होता

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) 
    }); 
}); 
+0

आप टाइमर ऑब्जेक्ट संदर्भ लीक कर रहे हैं। – legege

+0

मुझे इसे सर्वर पुनरारंभ करने में सहेजने की ज़रूरत है ... – user730569

+0

@ user730569 यह काम नहीं करेगा ... टाइमर पुनरारंभ करने के बाद चला जाएगा। पुनरारंभ करने के बाद आपको उन्हें फिर से निर्धारित करने का एक तरीका ढूंढना होगा। आप प्रारंभ समय को जारी रख सकते हैं, और फिर से शुरू करने पर टाइमआउट मान को फिर से समझ सकते हैं। – legege

0

मैं क्या करने की कोशिश की गई थी ओपी के समान ही बात। मेरे समाधान मेरी डिस्कनेक्ट हैंडलर में टाइमआउट के भीतर एक नया कुंजी पर एक सशर्त चेक के साथ समय समाप्ति सेट करने के लिए किया गया था:

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); 

टाइमआउट खुद को सर्वर के पुनरारंभ होने के दौरान जारी रहता नहीं हैं, लेकिन अगर आप स्टार्टअप पर स्वीपर विधि बंद लात द्वारा कि हल कर सकते थे। कनेक्टेड क्लाइंट वापस "ऑनलाइन" वापस आ जाएंगे।