TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Escape from Callback Hell

107 点作者 ianbishop大约 12 年前

19 条评论

Swizec大约 12 年前
I honestly find "callback hell" a lot easier to follow and understand than the vast majority of fixes everyone is coming up with.<p>They're just continuations, seriously, what's everyone's problem? You define a function, it gets access to the current scope, it defines the rest of the program flow.<p>If you feel like your code is nesting too deep, you define the function elsewhere and just reference it by name. Then you don't get access to the current scope.<p>Why is this so difficult to people?
评论 #5311734 未加载
评论 #5314896 未加载
评论 #5312331 未加载
评论 #5313319 未加载
评论 #5312161 未加载
评论 #5311992 未加载
etrinh大约 12 年前
Good overview of jQuery Deferred and how to use promises (at least the jQuery flavor). Promises (or futures) are a simple concept: an object-level abstraction of a non-blocking call, but they're very powerful when you see them in action. For example, the $.when method:<p>Let's say you have 3 ajax calls going in parallel. With $.when, you can attach callbacks to arbitrary groupings of those ajax calls (callback1 runs when ajax1 and ajax2 are done, but callback2 runs when ajax1 and ajax3 are done).<p>I first learned about promises in Trevor Burnham's excellent book Async Javascript (<a href="http://pragprog.com/book/tbajs/async-javascript" rel="nofollow">http://pragprog.com/book/tbajs/async-javascript</a>) and it is still the best explanation of promises I've ever read. If you like this article and are interested in reading further about promises or the asynchronous nature of Javascript in general (both for browser and node.js), I highly recommend you check out this book.
评论 #5311757 未加载
daleharvey大约 12 年前
I dont find that promises really help callback hell that much, they are useful but in the case of doing a series of sequential async functions the result is pretty similiar (the promises version is usually longer)<p>I got to write some firefox only code recently and added a delay to a function by just adding<p><pre><code> ... some code setTimeout(continueFun, 5000) yield; ... more code </code></pre> it felt like magic, I dont like generators and would much prefer to see message passing and blocking calls like erlang, but failing that it will be nice to be able to use generators more regularly
评论 #5312708 未加载
评论 #5312682 未加载
评论 #5315066 未加载
评论 #5314999 未加载
digisth大约 12 年前
A great library for structuring your callbacks is "async":<p><a href="https://github.com/caolan/async" rel="nofollow">https://github.com/caolan/async</a><p>I've only used it with node.js, but it's supposed to work in web browsers as well.<p>It allows you to think a little more procedurally ("waterfall" is especially handy here) while writing CPS code. Very good.
评论 #5311933 未加载
评论 #5314661 未加载
pkulak大约 12 年前
It's a real shame to have a language this high level, yet still have to go through this much crap just to get things done. Manual memory management is easier than this. But while including GC in the runtime has it's drawbacks, there is no reason that a language can't just handle task switching for you (like Go does, for example).
评论 #5311924 未加载
harshaw大约 12 年前
Deferreds are cool although they have their own set of issues. Mainly, that when you start chaining them there are situations where it can be a bit counterintuitive what is going on. My background is the Deferred from Twisted and Reimplemented in MochiKit.<p>You really need to read the Deferred implementation if you are going to use it. Otherwise you are asking for trouble long term. Of course, the other issue is that you may run into challenges explaining deferred's to your co-workers. :)<p>Twisted explored some cool ideas where you basically would write asynchronous code in an interative style using a blend of iterators and generators. Sadly until Javascript has those capabilities in every browser (and not just Firefox) I don't think it is possible.
评论 #5311843 未加载
spion大约 12 年前
If you want this problem solved, vote on the generators issue in v8:<p><a href="http://code.google.com/p/v8/issues/detail?id=2355" rel="nofollow">http://code.google.com/p/v8/issues/detail?id=2355</a><p>If v8 implements this, both Firefox and Chrome as well as node.js will have yield, enabling libraries like taskjs [1] to be used.<p>From taskjs.org:<p><pre><code> spawn(function*() { var data = yield $.ajax(url); $('#result').html(data); var status = $('#status').html('Download complete.'); yield status.fadeIn().promise(); yield sleep(2000); status.fadeOut(); }); </code></pre> [1]: <a href="http://taskjs.org/" rel="nofollow">http://taskjs.org/</a>
评论 #5313800 未加载
estavaro大约 12 年前
The main issue I have with "escaping from callback hell" is that it's a half-truth. Although I don't know much about how the Reactive Framework created by Microsoft works, I know they went well beyond the basics to try to make it all-encompassing coming closer to making it a full-truth.<p>Just transmitting data back and forth may play well to the strengths of your abstraction. But we have other uses with Timers that should also need such abstractions.<p>With Timers I have other needs like delaying the execution, resetting the delay countdown, stopping it before it executes it at all (like cancelling it), and finally with an Animation class I needed a way to finish executing a string of events in an instant in order to start a new animation. Also the Animation had other Animation versions at play that could need to be sped up before a new Animation started.<p>In .NET they seem to have a handy feature that waits the code to run before proceeding that comes into play with their .NET version of the Reactive Framework.<p>As far as I can tell, it's tough to really solve it. JavaScript doesn't have extra features like .NET does. We are more limited in what we can do. In Dart they have a version of this called Future that has been streamlined recently. As simple as it may seem to be, it comes with other related abstractions called Streams that altogether make it a bit daunting to escape from that hell only to land on the fire outright.
tomlu大约 12 年前
It seems like this problem would be elegantly solved by starting a thread, green thread or coroutine (depending on language) for each task and calling the API functions synchronously from within that. I'm not sure what support JS has for these things.
评论 #5313345 未加载
评论 #5312455 未加载
评论 #5311768 未加载
jart大约 12 年前
My favorite solution to this problem is a thing the OKCupid developers made called IcedCoffeeScript <a href="http://maxtaco.github.com/coffee-script/" rel="nofollow">http://maxtaco.github.com/coffee-script/</a>
评论 #5313763 未加载
lucian1900大约 12 年前
It seems odd that so many people defend callback nested chains. You end up writing in continuation passing style, when many compilers can do CPS transform for you (Scheme, C#, things like IcedCoffeeScript.
jj2大约 12 年前
If you have to deal with lots of nested callbacks, it's probably worth to use a CPS transformation like Streamline.js. It makes your code a lot cleaner. As if it was written synchronously.<p><a href="https://github.com/Sage/streamlinejs" rel="nofollow">https://github.com/Sage/streamlinejs</a> <a href="http://en.wikipedia.org/wiki/Continuation-passing_style" rel="nofollow">http://en.wikipedia.org/wiki/Continuation-passing_style</a>
iamwil大约 12 年前
I recently also tried my hand at promises using the node libs Q and when.<p>There's a gotcha with the progress handler. If you try to call the progress handler before the progress handler actually gets a chance to attach itself outside the function, it'll never actually fire. Some of the bugs with using promises are rather subtle.
cwiz大约 12 年前
I find LiveScript's back-calls (&#60;-) very elegant. In fact it makes concurrent code very easy to write and comprehend. Combined with async (<a href="https://github.com/caolan/async" rel="nofollow">https://github.com/caolan/async</a>) it is a pure joy.<p>As for pure JavaScript, dealing with callbacks is definitely not fun.
Offler大约 12 年前
I just don't understand the issue people are having here. Nested callbacks are a design choice, if you do not want nested callbacks stop writing code with them in it.<p>Here is a simple example in some Node.js code I've just written (I've never written any before this little project).<p><a href="https://github.com/Offler/node-bundler/blob/master/lib/bundler/filesystem/JSFileReader.js" rel="nofollow">https://github.com/Offler/node-bundler/blob/master/lib/bundl...</a><p>As you can see you just need to write in an OO manner and use function.bind(this) and Bob's your uncle. Really don't get the difficulty.
Too大约 12 年前
<p><pre><code> function getItem(id) { return $.get("/api/item/" + id); } $.when(getItem(3), getItem(4)).then(handleSuccess, handleFailure); </code></pre> Maybe I'm taking the point of the example out of context here, but i worry that promises makes it too easy to write non thought through code like this. Why make two separate http-requests for something that should have been possible to do with one?<p>Future prediction: Someone will create code similar to the one above but inside a for-loop calling getItem hundreds of times instead of just 2.
评论 #5313581 未加载
moe大约 12 年前
If only someone could come up with an abstraction over all this... We could perhaps call it threads, or co-routines, or such. It could make things so much easier!
rorrr大约 12 年前
&#62; "This is better, it definitely makes it clearer what exactly is going on"<p><pre><code> function createItem(item, successCallback, errorCallback) { var req = $.post("/api/item", item); req.success(successCallback); req.error(errorCallback); } </code></pre> How is this more clear than the default jQuery $.post?
评论 #5313786 未加载
评论 #5313906 未加载
bestest大约 12 年前
Well, frankly, it looks like you're jumping from one sheep to another. Using deferreds does NOT make more sense, and is actually even more difficult to perceive as it's quite counter-intuitive. MVVM is the way to go for web apps. Actually, anything else would be better than this.<p>The methods and approaches jQuery provides should not be used as a mainframe to achieve your goal, they should only be used as helpers here and there if ever.
评论 #5313389 未加载