JavaScript/JQuery:避免异步函数/匿名回调函数嵌套的最佳方法
我的JavaScript代码包含很多异步函数。例如,我使用D3.JS读取CSV文件,并连接到Google Maps API以查找两个地址之间的行驶方向 我使用on StackOverflow来等待异步函数完成(以避免返回带有JavaScript/JQuery:避免异步函数/匿名回调函数嵌套的最佳方法,javascript,asynchronous,Javascript,Asynchronous,我的JavaScript代码包含很多异步函数。例如,我使用D3.JS读取CSV文件,并连接到Google Maps API以查找两个地址之间的行驶方向 我使用on StackOverflow来等待异步函数完成(以避免返回带有未定义值的变量)。但是,因为我有很多异步函数,所以我有很多嵌套的匿名回调函数: carDirections(from, to).done(function(car) { transitDirections(from, to).done(function
未定义值的变量)。但是,因为我有很多异步函数,所以我有很多嵌套的匿名回调函数:
carDirections(from, to).done(function(car) {
transitDirections(from, to).done(function(train) {
// carDirections and trainDirections have similar anonymous callback functions.
function carDirections(from, to) {
var dfd = $.Deferred();
var directionsService = new google.maps.DirectionsService;
directionsService.route({
origin: from,
destination: to,
travelMode: google.maps.TravelMode.DRIVING
}, function(response, status) {
if (status === google.maps.DirectionsStatus.OK) {
dfd.resolve(response.routes[0].legs[0]);
}
});
return dfd.promise();
}
// Similar code for transitDirections.
这导致了大量的done
和Deferred
函数,这使得代码很难理解。有没有合适的方法来解决这个问题?例如,我可以重新编程我的谷歌地图功能,使其同步,还是有其他功能(更简单)只有在上一个函数返回变量时才继续执行代码的方法?据我所知,列车方向不需要从CardDirections获得任何响应,您只需要在所有操作完成后启动回调
您可以使用延迟对象
var deferredObj1 = $.Deferred(),
deferredObj2 = $.Deferred();
$.when(deferredObj1,deferredObj2).done(function(){
console.log("They are both done!");
});
// inside the Event1 handler:
deferredObj1.resolve();
// inside the Event2 handler:
deferredObj2.resolve();
jQuery1.5中引入的延迟对象是一个可链接的实用程序
通过调用jQuery.Deferred()方法创建的对象。它可以
将多个回调注册到回调队列中,调用回调
队列,并中继任何同步或
异步函数
您可能想了解更多关于Promise
s的内容。您可以像这样链接异步操作
asyncOp1()
.then(result1 => asyncOp2(result1))
.then(result2 => asyncOp3(result2))
.then(result3 => Promise.all(asyncOp4(result3), asyncOp5(result3)))
.catch(error => { /* deal with an error */ })
// ...
如果所有操作都返回承诺
(这有助于避免嵌套)。(上述ES5伪代码和承诺(如果需要)。
)
如果您正在寻找不同的方法来处理复杂的异步代码,请查看。。。这并不是说如果你这样做,我会承担任何责任:)你有没有研究过承诺?@blessenm是的,这就是我在上面的帖子中尝试的。这导致了大量的承诺,我想知道这是否可以避免。这似乎是一个很好的解决方案,谢谢!但是,如果我有以下代码:carDirections(from,to).then(car=>trainDirections(from,to)).then(train=>console.log(car))代码>,变量car
不再可访问。除了将此变量作为函数参数发送外,还有其他方法可以继续传递此变量吗?您可以将其保存到外部作用域变量或扩展Promise
monad以收集链中的所有结果,但只发送所需的内容是最简单和最透明的。如果你不想污染你的火车操作功能,你可以一直做carOp()。然后(car=>trainOp(car)。然后(train=>({car,train}))。然后({car,train})=>…)
。