javascript - Deferred chain crashing browser -
this small function should able open , close box. opening , closing needs take account css transitions, figured can use $.deferred
.
here's relevant code:
function test(){ // these assigned deferred objects during transitions this.opening = this.closing = false; this.isopen = false; this.x = $('<div />').appendto('body'); this.x.width(); } test.prototype.open = function(){ // box opening: return opening deferred if(this.opening) return this.opening; // box closing: chain // supposed wait box close, // open again if(this.closing) return this.closing.then((function(){ return this.open(); }).bind(this)); // box open, resolve if(this.isopen) return $.when(); console.log('opening'); this.opening = new $.deferred(); this.x.addclass('open'); settimeout((function(){ this.opening.resolve(); this.opening = false; this.isopen = true; }).bind(this), 1000); return this.opening; };
the close() function open() in reverse.
the problem appears when try close box while it's being opened, or vice-versa. example:
var t = new test(); t.open(); // takes 1 second // call close() after 0.05s settimeout(function(){ t.close(); }, 50);
it appears there's stack overflow happening or that. know what's causing it?
the entire test code here, higher timeout value doesn't crash chrome.
i notices several issues code:
returning deferred objects instead of promises, can execute .then() on promises
overriding deferred variable bool value, using deferred.state() instead
this updated version of code:
function test(){ this.opening = this.closing = false; this.isopen = false; this.x = $('<div />').appendto('body'); this.x.width(); } test.prototype.open = function(){ if(this.opening && this.opening.state() == 'pending') return this.opening.promise(); if(this.closing && this.closing.state() == 'pending') return this.closing.promise().then((function(){ return this.open(); }).bind(this)); if(this.isopen) return $.when(); console.log('opening'); this.opening = new $.deferred(); this.x.addclass('open'); settimeout((function(){ this.isopen = true; this.opening.resolve(); }).bind(this), 1000); return this.opening.promise(); }; test.prototype.close = function(){ if(this.opening && this.opening.state() == 'pending') { console.log('opening pending'); return this.opening.promise().then((function(){ console.log('opening resolved'); return this.close(); }).bind(this)); } if(this.closing && this.closing.state() == 'pending'){ console.log('closing pending'); return this.closing.promise(); } if(!this.isopen) return $.when(); console.log('closing'); this.closing = new $.deferred(); this.x.removeclass('open'); settimeout((function(){ console.log('closing resolved'); this.closing.resolve(); this.isopen = false; }).bind(this), 1000); return this.closing.promise(); }; var t = new test(); t.open(); settimeout(function(){ t.close(); }, 15);
the output:
"opening" "opening pending" "opening resolved" "closing" "closing resolved"
Comments
Post a Comment