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进行操作时调用该函数。
我仍在努力适应 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进行操作时调用该函数。