JavaScript:使用回调控制程序流程

JavaScript: using callbacks to control program flow

我仍在努力适应 JS,最近在理解回调的作用方面遇到了很多麻烦。

我可以看到回调提供了一种更加异步(?)的方法来返回函数中生成的值。例如,这对我来说很有意义:

function summation (a, b, _callback) {
 if (typeof(_callback) === 'function') {
  _callback(a+b);
 }
}

$(document).ready(function () {
 summation(2,3,function (_val) {
  console.log(_val);
 }
});

var _val = summation(2,3); 之类的东西相反,其中 var 在分配后不能立即使用。

当我尝试使用 jQuery 操作网页上的元素时,我很难扩展此过程。我有一个跟踪元素的对象:

function createObj (_callback) {
 var test = new Object();
 test.mainPane = $('#mainPane');
 if (typeof(_callback) === 'function') {
  _callback(test);
 }
}

如果我想将 test.mainPane 传递给一个函数 fitToPage() 以调整元素的属性以适应给定的屏幕尺寸,然后想将元素传递给另一个函数 createElems() 将子项添加到元素,事情开始分崩离析:

$(document).ready(function () {
 createObj(function (test) {
  fitToPage(test, function (test) {
   createElems(test, null);
  });
 });
});

如果我尝试通过创建特殊函数来避免这种回调地狱(?),情况似乎只会变得更糟,这些函数除了帮助我管理对其他函数的回调之外什么都不做。我确信我错过了一些重要的东西,但还没有想出正确的搜索词来找到它。有没有更好的方法?

您已经 运行 解决了使用回调处理异步代码所涉及的主要问题之一。异步性是会传染的。一旦你开始在一个地方使用它,周围的代码也需要它,然后是周围的代码,依此类推。

目前比较流行的处理方法之一是 Promises。这些实际上并没有消除回调问题,但它们让您可以在语法上以更简单的方式处理它们。这个想法是,函数 returns 不是接受回调,而是一个对象,调用者可以将回调附加到该对象,稍后将对其进行处理。在 promise 库中,这些对象必须公开一个 then 方法,该方法接受一个 success 和一个 error 回调。我不知道 jQuery 的 ready 方法是否公开了它,所以这可能不太正确,但它应该接近于如何使用 Promises 重写示例:

$(document).ready()
    .then(createObj)
    .then(fitToPage)
    .then(function(test) {return createElems(test, null)});

如果您的 createElems 版本部分应用了 null,那么最后一行可能只是

    .then(createElems2);

JavaScript 执行模型在设计上是同步的。因此,如果您在代码中调用函数,函数体将立即、同步地执行,而不会被其他任务中断。因此这个

function summation(a,b) {
  return a + b;
}
var r = summation(1,2); // -> 3

会按原样执行。

同时,您可以要求浏览器运行时环境在某些事件发生时调用[返回]您的函数(回调本身)。因此你的函数将被异步调用:

function doSomethingWhenDocumentIsLoaded() 
{
  // document ready, do something with it.
}

$(document).ready(doSomethingWhenDocumentIsLoaded);

这里我们定义了函数,并要求运行时在文档loaded/ready进行操作时调用该函数。