我的JavaScript代码包含很多异步函数。例如,我正在使用D3.JS来读取CSV文件,并且我正在连接到Google Maps API以查找两个地址之间的行车路线。
我在StackOverflow上使用this answer等待异步函数完成(以避免返回值为undefined
的变量)。但是,因为我有很多异步函数,所以我有很多嵌套的匿名回调函数:
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
函数的意大利面,这使得代码很难理解。有没有正确的方法来解决这个问题?例如,我可以重新编程我的Google Maps函数以使它们同步,还是有另一种(更简单的方法)只在前一个函数返回变量时才继续执行代码?
答案 0 :(得分:1)
您可能希望read up更多关于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 */ })
// ...
如果所有操作都返回Promise
(这有助于避免嵌套)。 (Transpile上述伪代码到ES5,polyfill Promise
,如果需要的话。)
如果您正在寻找完全处理复杂异步代码的不同方法,请查看RxJS ...如果您这样做,我不承担任何责任:)
答案 1 :(得分:0)
据我所知,trainDirections不需要从carDirections获得任何响应,您只需要在所有操作完成后触发回调?
您可以使用延迟对象。
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();
jQuery 1.5中引入的Deferred对象是一个可链接的实用程序 通过调用jQuery.Deferred()方法创建的对象。它可以 将多个回调注册到回调队列中,调用回调 队列,并中继任何同步或成功或失败状态 异步功能。