最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript callback hell with setTimeout(); - Stack Overflow

programmeradmin0浏览0评论

Aloha. This is my first question here after eons of lurking. I apologize for the verbose but direct form of this question -- as well as the limitations on acceptable answers -- but I am here to contribute. I have a problem that other questions (for example How to avoid long nesting of asynchronous functions in Node.js or Chained callback readability in Javascript?) do not answer to my satisfaction.

I want to perform several Javascript callbacks so that I have a sequence of four actions occurring one after another. Here is the source:

var self = this;
fade(div, fadeIn, -20, function() {
  load(unload, dataOut, -10, function() {
    load(self, dataIn, 10, function() {
      fade(div, fadeOut, 20),0);
      unload = self;}
    );}
  );}
);

The load() and fade() functions are very similar except for internal semantic details, and they look something very similar to this:

function load(menuCategory, data, step, callback) {
  menuCategory.parentNode.style.width = data+"px";
  data += step;
  if(dataIn <= data && data <= dataOut) {
    setTimeout(function() { load(menuCategory,data,step,callback) }, 15);
  } else if(callback && (typeof(callback) == 'function')) { 
    callback();}
}

I have several questions associated with this mess, but first let me give you the answers I am NOT looking for. Answers using jQuery are not acceptable. Answers using other timing or "synchronicity" frameworks or modules are not acceptable. Answers questioning the reason for blocking execution are not acceptable. Answers using languages other than Javascript are unacceptable. Non-abstract answers are acceptable, but the final solution will need to be as abstract as possible, meaning the answer must be able to act on a variety of similar but slightly different actions.

Here is my primary question: Is there a function/object I could use to apply these actions sequentially, to cut down on the callback hell going on here? In other words, what would an object look like if the object/function were able to synchronously execute each action as it was individually iterated through it (i.e. passed to it)?

Secondary question: Is anyone aware of how much this callback business looks like goto() in other languages? Meaning, this nesting of callbacks feels very awkward and inelegant to me. Is there a Javascript language construct either being developed or already developed that will reduce this crazy business? Callback nesting is some of the hardest logic flow to follow. It just feels awkward.

My goal here is a tight, elegant, attractive, homegrown Javascript object/function -- that I can call in a for() loop or equivalent -- to apply these operations on each action in sequence. If you've read this far I want to thank you for your time and consideration. :)

Aloha. This is my first question here after eons of lurking. I apologize for the verbose but direct form of this question -- as well as the limitations on acceptable answers -- but I am here to contribute. I have a problem that other questions (for example How to avoid long nesting of asynchronous functions in Node.js or Chained callback readability in Javascript?) do not answer to my satisfaction.

I want to perform several Javascript callbacks so that I have a sequence of four actions occurring one after another. Here is the source:

var self = this;
fade(div, fadeIn, -20, function() {
  load(unload, dataOut, -10, function() {
    load(self, dataIn, 10, function() {
      fade(div, fadeOut, 20),0);
      unload = self;}
    );}
  );}
);

The load() and fade() functions are very similar except for internal semantic details, and they look something very similar to this:

function load(menuCategory, data, step, callback) {
  menuCategory.parentNode.style.width = data+"px";
  data += step;
  if(dataIn <= data && data <= dataOut) {
    setTimeout(function() { load(menuCategory,data,step,callback) }, 15);
  } else if(callback && (typeof(callback) == 'function')) { 
    callback();}
}

I have several questions associated with this mess, but first let me give you the answers I am NOT looking for. Answers using jQuery are not acceptable. Answers using other timing or "synchronicity" frameworks or modules are not acceptable. Answers questioning the reason for blocking execution are not acceptable. Answers using languages other than Javascript are unacceptable. Non-abstract answers are acceptable, but the final solution will need to be as abstract as possible, meaning the answer must be able to act on a variety of similar but slightly different actions.

Here is my primary question: Is there a function/object I could use to apply these actions sequentially, to cut down on the callback hell going on here? In other words, what would an object look like if the object/function were able to synchronously execute each action as it was individually iterated through it (i.e. passed to it)?

Secondary question: Is anyone aware of how much this callback business looks like goto() in other languages? Meaning, this nesting of callbacks feels very awkward and inelegant to me. Is there a Javascript language construct either being developed or already developed that will reduce this crazy business? Callback nesting is some of the hardest logic flow to follow. It just feels awkward.

My goal here is a tight, elegant, attractive, homegrown Javascript object/function -- that I can call in a for() loop or equivalent -- to apply these operations on each action in sequence. If you've read this far I want to thank you for your time and consideration. :)

Share Improve this question edited May 23, 2017 at 11:54 CommunityBot 11 silver badge asked Sep 26, 2012 at 0:47 L0j1kL0j1k 12.6k7 gold badges58 silver badges65 bronze badges 3
  • 2 I think the question "Why do you use setTimeout(func(),0)?" is very legitimate, as neither your fade nor your load function return functions that could be timed-out with setTimeout. Is this a flaw in your question or is it the actual reason for your code mess? – Bergi Commented Sep 26, 2012 at 0:54
  • javascript.info/tutorial/events-and-timing-depth – L0j1k Commented Sep 26, 2012 at 1:14
  • 2 You could try making a fake stack as an array of objects fakeStack = [], where the arguments to fade or load as key/value pairs in the objects, fakeStack.push({cat:div, data:fadeIn, step:-20}) then work with fakeStack[0] and when you meet the end of the loop, call again fakeStack.shift(). – Paul S. Commented Sep 26, 2012 at 2:39
Add a ment  | 

3 Answers 3

Reset to default 6

using setTimeout(func(),0) in order to execute synchronously

No. Either use func() for a synchronous execution, or setTimeout(func, 0) to queue the execution (which makes it asynchronous).

Is setTimeout(func[…],0) the "most elegant" way to put this action onto the execution queue for rendered webpage objects? In other words, is there a "more elegant" way to block execution (i.e. do these things sequentially)?

Yes, this is the standard method. However, this does not block execution, and has nothing to do with sequencing. If the execution is synchronous, just execute it, if not you will have to deal with the callbacks and queuing a new task does not help.

Is anyone aware of how much this callback business looks like goto() in other languages? Meaning, this nesting of callbacks feels very awkward and inelegant to me. Is there a Javascript language construct either being developed or already developed that will reduce this crazy business?

No, I'm not aware of other languages, but afaik goto is a synchronous, control-flow-structuring statement as does not deal with asynchronous actions.

But no, there are no JavaScript language constructs ("syntactic sugar") that help us around the continuation-passing style with its callback hell.

Is there a function/object I could use to apply these actions sequentially, to cut down on the callback hell going on here? In other words, what would an object look like if the object/function were able to synchronously execute each action as it was individually iterated through it (i.e. passed to it)?

My goal here is a tight, elegant, attractive, homegrown Javascript object/function -- that I can call in a for() loop or equivalent -- to apply these operations on each action in sequence.

Again you want "sequencially" instead of "synchronous" :-) Yes, there are [handcoded/homegrown] solutions which make dealing with callbacks easier. As those callback organisation libraries you mentioned do not satisfy you, I'd remend to look into the very elegant and attractive Promise Api and its Deferred objects (see futures and promises for the concept).

I'm unsure why you're using setTimeout at all here. Its not necessary to queue callbacks. The following structure will work, assuming that fade() and load() handle callback execution correctly.

fade(div, fadeIn, -20, function() {
    load(unload, dataOut, -10, function() {
        load(self, dataIn, 10, function() {
            fade(div, fadeOut, 20),0);
        });
    )};
)};

Another topic you should look into is Promises, also called deferreds and futures. Its essentially a coding pattern that specifically handles nested callbacks. At root, you create a Promise object that gets returned immediately, then when your method is done executing it fires a method on the promise that can then execute your next function. Its a different way of writing javascript, but easy to understand and very useful.

As it turns out, the practice that fits as the "best" answer to my question is events. In particular the practice I'm referring to is best described by EventEmitter on Node.js, or creating custom events and event listeners on client browsers. While the Promise API and its deference model is intriguing, it uses extensions to the language instead of core Javascript, which is what I was looking for here in particular (and thus why none of the previous answers -- despite their clarity -- support exactly what I was looking for).

This link (http://wekeroad./2012/04/05/cleaning-up-deep-callback-nesting-with-nodes-eventemitter) provides a very good example of what I was looking for. As well, I should mention the book "Async Javascript" by Trevor Burnham (http://www.amazon./Async-JavaScript-Trevor-Burnham/dp/1475247362), and "Secrets of the JavaScript Ninja" by John Resig and Bear Bibeault (http://www.amazon./Secrets-JavaScript-Ninja-John-Resig/dp/193398869X). These books provide extremely clear working examples of custom events and event handlers in client browsers that provide an elegant way around this "callback hell" I was referring to.

发布评论

评论列表(0)

  1. 暂无评论