-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infinite recursion #43
Comments
Here is an example of Backbone + jQuery + when.js when some infinite recursion happens: |
So, actually, here is a shorter version of how this fails. I thought I've used this before and it used to work, strange. var success = function () {
console.log('success');
}
var error = function () {
console.log('error');
}
var request = $.get("/will_fail");
// both of these fail, as in they do the 100% CPU thing on my Chrome
when(request).then(success, error);
when(request, success, error); |
Very strange! I did a little investigating in your original fiddle, added some different cases, and tried it in Firefox and Safari as well. The results are pretty weird. In FF 12, all the cases work just fine, and no CPU spike. In Safari and Chrome, all the cases actually work correctly--that is, they produce the expected output to the console. However, the Here's my version of the fiddle It's interesting that simply doing a I'll try your simplified example and see what I can find. If you find any more clues, let me know! |
Here's another fiddle that shows using dojo.xhrGet works correctly, but $.get() causes some sort of CPU spike or an XHR lockup in both FF 12 and WebKit. It's starting to seem like some sort of problem with |
FWIW, I haven't actually witnessed infinite recursion. I see the CPU spike, but it seems to happen after execution leaves the when.js code due to the XHR promise rejection (in Chrome), or due to the XHR locking up (in FF). Have you been able to trace the recursion in a debugger and actually see it, or have you gotten a "maximum stack depth exceeded" type error from Chrome? Might be another clue ... |
Ok, I think I did find some sort of infinite recursion by using Firebug's profiler. Still not sure exactly what's going on, but I'll spend some time on this a bit later today and post more info. |
I've seen this outside of jsfiddle first. I've put console.logs in a bunch of when.js internal functions and I saw all of those logs happen in Chrome's console over and over, thus my point about something recursing in when.js. |
Cool, thanks for the info. I am def seeing some sort of recursion, but also not seeing the callstack grow infinitely, it's as if the recursion is actually happening across multiple turns of the javascript event loop. And most of the time in FF, I don't see it at all--it works correctly. I'll keep you posted, and let me know if you find anything else! |
I found the issue. It's a rather odd interaction between
So, what happened was that the From there, the cycle just continued forever. One potential workaround is to ensure that your promise callbacks and errbacks return something (other than the I've pushed a potential fix to the issue-43 branch. Can you try it and let me know if it fixes the problem? Also, here is an html file that uses the issue-43 branch. You can save and run it locally to test: <!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="https://raw.github.com/cujojs/when/issue-43/when.js"></script>
<script type="text/javascript">
function success(val) { console.log('success', val); }
function fail(e) { console.error('fail', e); }
// Each of these should work without causing a cpu spike
when($.get('fake.html'), success, fail);
// when($.get('fake.html')).then(success, fail);
// when.map(['1', '2', '3'], function(url) {
// return $.get(url);
// }).then(success, fail);
</script>
</head>
<body>
</body>
</html> |
The issue-43 branch works perfectly with this test html you provided as well as in my app, As far as I understood you simply removed that forwarding of the previous value feature in case the callbacks return undefined? When would that feature be important? I think some kind of fix for this problem is definitely needed as I'm sure someone else will run into the same problem when mixing when and jquery. Another possible way to solve this problem might be not converting foreign promises into when.js promises automagically. What if there was a function like when.convert that does that. So then you would do: when.map(someBackboneModels, function (model) {
// we know .save returns jquery deferred, so need to convert to when.js deferred
return when.convert(model.save());
}) This would mean less magic and make developers more aware of those differences in promises. I'm not even sure this would solve this particular issue. Anyways, the fix you made also seems to be working, so I would be happy to see that go live. Any doubts about it? Thanks for the quick responses. |
Cool, glad that works for you, and yep, you're right that the change was to stop forwarding the previous value when a callback returns undefined. That "feature" was implemented pretty early-on in when.js, and I've come to realize it's just plain wrong :) So, I have no doubts that this change represents the correct behavior :) In fact, issue #31 is already tracking it, and it had already been implemented in the dev-20 branch. Right now, it's slated for when.js 2.0.0, but I think you're right that compatibility with It's not entirely clear to me, based on semantic versioning rules, whether this change could be released in a 1.3.0 version, or whether it would require a 2.0.0 bump. It'll go out in the next release, be it numbered 1.3.0 or 2.0.0. Since we know the answer to the specific problem, and #31 is already tracking the change, I'm closing this issue, but feel free to reopen if you run into any additional related problems. |
Hey @KidkArolis, just wanted to let you know v1.3.0 is released and includes this fix. Cheers! |
I just had a problem with when.js + jquery's deferreds.
In case of success, everything works as expected. In case of the error, when.js starts calling it's internal functions recursively and kills the browser..
I will try to reproduce/identify the problem, but do you spot anything wrong with the above?
The text was updated successfully, but these errors were encountered: