2012-09-26 51 views
-1

阿罗哈。这是我潜伏后的第一个问题。我对这个问题的详细而直接的形式以及对可接受答案的限制表示歉意 - 但我在这里作出贡献。我有一个问题,其他问题(例如How to avoid long nesting of asynchronous functions in Node.jsChained callback readability in Javascript?)不能满足我的要求。带有setTimeout()的Javascript回调地狱;

我想要执行多个Javascript回调,以便我有一个接一个发生的四个动作序列。这里是源:

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

的load()和淡入淡出()函数,除了内部语义细节十分相似,而且他们看起来非常类似于这样:

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

我有几个问题与这个混乱相关,但首先让我给你我没有找到的答案。使用jQuery的答案是不可接受的。使用其他计时或“同步”框架或模块的答案是不可接受的。质疑阻止执行的原因的答案是不可接受的。使用JavaScript以外的语言的答案是不可接受的。非抽象的答案是可以接受的,但最终的解决方案将需要尽可能抽象,这意味着答案必须能够采取各种类似但略有不同的行动。

这里是我的主要问题: 是否有一个函数/对象,我可以用它来顺序应用这些动作,以减少在这里回调地狱?换句话说,如果对象/函数能够同步执行每个动作(因为它是通过它单独迭代的)(即传递给它),对象将会是什么样子?

次要问题: 是任何人都清楚这一点回调业务多少看起来像在其他语言中的goto()?意思是,这种回调嵌套感觉对我来说非常尴尬和不雅。是否有正在开发或已经开发的Javascript语言结构可以减少这种疯狂的业务?回调嵌套是一些最难遵循的逻辑流程。它只是感觉尴尬。

我的目标是一个严密的,优雅的,有吸引力的,土生土长的Javascript对象/功能 - 我可以在一个for()循环或等效通话 - 在序列中的每个动作应用这些操作。如果你已经读了这么多,我想感谢你的时间和考虑。 :)

+2

我想这个问题“*为什么你使用'setTimeout(func(),0)'?*”是非常合法的,因为你的'fade'和'load'函数都不会返回可能超时的函数与['setTimeout'](https://developer.mozilla。组织/ EN-US /文档/ DOM/window.setTimeout)。这是你的问题的缺陷,或者它是你的代码混乱的实际原因? – Bergi

+0

http://javascript.info/tutorial/events-and-timing-depth – L0j1k

+2

你可以尝试制作一个假堆栈作为对象'fakeStack = []'的数组,其中'fade'或'load'的参数为对象中的键/值对,'fakeStack.push({cat:div,data:fadeIn,step:-20})'然后使用'fakeStack [0]',当你遇到循环结束时,再次调用'fakeStack.shift()'。 –

回答

6

为了执行同步

号既可以使用func()用于同步执行,或setTimeout(func, 0)排队的执行(这使得它异步)使用setTimeout(func(),0)

setTimeout(func[…],0)这个“最优雅”的方式把这个动作放到渲染的网页对象的执行队列上吗?换句话说,是否有一种“更优雅”的方式来阻止执行(即顺序执行这些操作)?

是的,这是标准方法。但是,这并不是块的执行,并且与排序无关。如果执行是同步的,只是执​​行它,如果没有,你将不得不处理回调和排队新任务没有帮助。

有人知道这个回调业务在其他语言中看起来像goto()吗?意思是,这种回调嵌套感觉对我来说非常尴尬和不雅。是否有正在开发或已经开发的Javascript语言结构可以减少这种疯狂的业务?

不,我不知道其他语言的,但据我所知goto是同步,控制流的结构化语句如不处理异步操作。

但是,没有,没有JavaScript语言结构(“语法糖”),以帮助我们的continuation-passing style其回调地狱左右。

有没有一个函数/对象我可以用来顺序应用这些动作,以减少在这里进行的回调地狱?换句话说,如果对象/函数能够同步执行每个动作(因为它是通过它单独迭代的)(即传递给它),对象将会是什么样子?

我的目标是一个严密的,优雅的,有吸引力的,土生土长的Javascript对象/功能 - 我可以在一个for()循环或等效通话 - 在序列中的每个动作应用这些操作。

再一次,你想“顺序”而不是“同步”:-)是的,有[handcoded/homegrown]解决方案,使处理回调更容易。由于您提到的those callback organisation libraries不符合您的要求,我建议您查看非常优雅和有吸引力的Promise Api及其延期对象(请参阅futures and promises了解该概念)。

+1

谢谢你的回答。这是非常有用的,虽然我还不能upvote。 :P – L0j1k

+0

我会接受这个答案,因为它提供了我迄今听到的有关回调嵌套的最全面的答案。马哈洛和阿罗哈。 – L0j1k

+1

哇。对于一年前没有接受这一点抱歉。抱歉! :) – L0j1k

2

我不确定你为什么在这里使用setTimeout。它不需要排队回调。假设fade()和load()正确处理回调执行,以下结构将起作用。

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

你应该看看的另一个话题是Promises,也称为延期和期货。它本质上是一种专门处理嵌套回调的编码模式。在根目录下,您创建了一个Promise对象,该对象立即返回,然后当您的方法完成后,它会触发承诺中的一个方法,然后执行您的下一个函数。它是一种编写javascript的不同方式,但易于理解且非常有用。

+0

我删除了代码的setTimeout(func(),0)部分,以更清楚地说明主要问题。谢谢您的回答。我无法赞成,但你的答案是有用的。 – L0j1k

1

事实证明,适合作为我的问题的“最佳”答案的做法是事件。特别是我所指的实践最好由Node.js上的EventEmitter来描述,或者在客户端浏览器上创建自定义事件和事件监听器。尽管Promise API及其遵从模型非常有趣,但它使用语言的扩展而不是核心Javascript,这正是我在这里特别寻找的(也就是为什么以前的答案 - 尽管它们很清晰 - 都不支持我在找什么)。

此链接(http://wekeroad.com/2012/04/05/cleaning-up-deep-callback-nesting-with-nodes-eventemitter)提供了我正在寻找的一个很好的例子。另外,我应该提及Trevor Burnham(http://www.amazon.com/Async-JavaScript-Trevor-Burnham/dp/1475247362)的书“Async Javascript”以及John Resig和Bear Bibeault撰写的“JavaScript忍者的秘密”(http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X)。这些书提供了非常清晰的客户端浏览器中自定义事件和事件处理程序的工作示例,这些示例提供了我所指的“回调地狱”的优雅方法。