简介:尽管使用了异步代码和回调,是否可以遵循一些完善的最佳实践模式来使代码保持可读性?
我正在使用一个JavaScript库,该库异步执行很多工作,并且严重依赖于回调。看来编写一个简单的“负载A,负载B ...”方法变得相当复杂,并且很难使用此模式进行操作。
让我举一个(人为的)例子。假设我要从远程Web服务器(异步)加载一堆图像。在C#/ async中,我将编写如下内容:
disableStartButton();
foreach (myData in myRepository) {
var result = await LoadImageAsync("http://my/server/GetImage?" + myData.Id);
if (result.Success) {
myData.Image = result.Data;
} else {
write("error loading Image " + myData.Id);
return;
}
}
write("success");
enableStartButton();
代码布局遵循“事件流”:首先,禁用开始按钮,然后加载图像(await
确保UI保持响应),然后再次启用开始按钮。
在JavaScript中,使用回调,我想到了这一点:
disableStartButton();
var count = myRepository.length;
function loadImage(i) {
if (i >= count) {
write("success");
enableStartButton();
return;
}
myData = myRepository[i];
LoadImageAsync("http://my/server/GetImage?" + myData.Id,
function(success, data) {
if (success) {
myData.Image = data;
} else {
write("error loading image " + myData.Id);
return;
}
loadImage(i+1);
}
);
}
loadImage(0);
我认为缺点很明显:我必须将循环重做为递归调用,应该在最后执行的代码在函数的中间,开始下载(loadImage(0)
)的代码在最底部,而且通常很难阅读和遵循。丑陋,我不喜欢它。
我确定我不是第一个遇到此问题的人,所以我的问题是:尽管使用异步代码和回调,我是否可以遵循一些完善的最佳实践模式来保持代码可读性?
LoadImageAsync
实际上是Ext.Ajax.request
对Sencha Touch 的调用。
async.waterfall
就是您的答案。