-1

阿罗哈。这是我潜伏多年后的第一个问题。对于这个问题的冗长但直接的形式,以及可接受答案的限制,我深表歉意,但我是来贡献的。我有一个问题,其他问题(例如如何避免 Node.js 中异步函数的长嵌套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() 和 fade() 函数非常相似,它们看起来非常相似:

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() 循环或等效循环中调用它——将这些操作按顺序应用于每个操作。如果你已经读到这里,我要感谢你的时间和考虑。:)

4

3 回答 3

6

使用setTimeout(func(),0)为了同步执行

否。要么func()用于同步执行,要么setTimeout(func, 0)将执行排队(使其异步)。

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

是的,这是标准方法。但是,这不会阻止执行,并且与排序无关。如果执行是同步的,只需执行它,否则您将不得不处理回调并且将新任务排队也无济于事

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

不,我不知道其他语言,但 afaikgoto是一个同步的控制流结构化语句,因为它不处理异步操作。

但是不,没有 JavaScript 语言结构(“语法糖”)可以帮助我们绕过带有回调地狱的延续传递风格。

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

我的目标是一个紧凑的、优雅的、有吸引力的、本地开发的 Javascript 对象/函数——我可以在 for() 循环或等效循环中调用它——将这些操作按顺序应用于每个操作。

再次,您想要“顺序”而不是“同步”:-) 是的,有 [手工编码/本土] 解决方案可以更轻松地处理回调。由于您提到的那些回调组织库不能满足您的要求,我建议您研究一下非常优雅和有吸引力的PromiseApi及其 Deferred 对象(请参阅概念的期货和承诺)。

于 2012-09-26T01:21:56.453 回答
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,也称为 deferreds 和 futures。它本质上是一种专门处理嵌套回调的编码模式。在根目录下,您创建一个立即返回的 Promise 对象,然后当您的方法执行完成时,它会触发一个可以执行下一个函数的 Promise 方法。它是一种不同的 javascript 编写方式,但易于理解且非常有用。

于 2012-09-26T01:15:29.987 回答
1

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

这个链接(http://wekeroad.com/2012/04/05/cleaning-up-deep-callback-nesting-with-nodes-eventemitter)提供了一个很好的例子来说明我在寻找什么。同样,我应该提到 Trevor Burnham 的“Async Javascript”一书(http://www.amazon.com/Async-JavaScript-Trevor-Burnham/dp/1475247362)和 John Resig 的“JavaScript Ninja 的秘密”和 Bear Bibeault ( http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X )。这些书提供了客户端浏览器中自定义事件和事件处理程序的非常清晰的工作示例,它们提供了一种优雅的方式来解决我所指的“回调地狱”。

于 2013-04-21T05:07:31.573 回答