Javascript 多个异步回调调用
我遇到多个异步调用的问题。我有三项任务要申请。首先,我从第一个请求中获取一些json数据。然后,当该请求完成后,我从另一个服务向getMovie Trailes发出多个请求,并将该数据合并到第一个响应中的每个对象。当所有这些都完成后,我想将数据写入json文件。很简单,但我没有兑现承诺 这是我的密码Javascript 多个异步回调调用,javascript,asynchronous,es6-promise,Javascript,Asynchronous,Es6 Promise,我遇到多个异步调用的问题。我有三项任务要申请。首先,我从第一个请求中获取一些json数据。然后,当该请求完成后,我从另一个服务向getMovie Trailes发出多个请求,并将该数据合并到第一个响应中的每个对象。当所有这些都完成后,我想将数据写入json文件。很简单,但我没有兑现承诺 这是我的密码 MovieService.getContent(config.url + '?key=' + config.moviekey).then(function(data) { var m
MovieService.getContent(config.url + '?key=' + config.moviekey).then(function(data) {
var movies = JSON.parse(data);
var cnt = 0;
var len = movies.length;
var results = [];
for (var i = 0; i < movies.length; i++) {
var imdbid = movies[i].ids.imdb;
(function (i, imdbid) {
MovieService.getContent(config.themoviedburl + 'tt' + imdbid + '/videos?api_key=' + config.themoviedbkey).then(function (data) {
len--;
movies[i].trailers = JSON.parse(data);
if (len === 0) {
FileService.writeToJson(JSON.stringify(movies), config.showtimesfilepath);
}
});
})(i, imdbid);
};
});
MovieService.getContent(config.url+'?key='+config.moviekey)。然后(函数(数据){
var movies=JSON.parse(数据);
var-cnt=0;
var len=movies.length;
var结果=[];
for(var i=0;i
现在可以了,但是如果循环中的一个请求失败了呢。然后我的计数器不正确,我会将数据写入文件。有人能帮我用承诺建立类似的场景吗。哦,是的,我的另一段代码是MovieService,它可以发出所有请求。使用promises对数组上的一系列操作进行排序的常见方法是使用
.reduce()
,其中每次迭代都会添加到一个promise链上,从而导致所有异步操作都被排序:
// in sequence
MovieService.getContent(config.url + '?key=' + config.moviekey).then(function(data) {
var movies = JSON.parse(data);
return movies.reduce(function(p, movie, index) {
return p.then(function() {
var imdbid = movie.ids.imdb;
return MovieService.getContent(config.themoviedburl + 'tt' + imdbid + '/videos?api_key=' + config.themoviedbkey).then(function (data) {
movies[index].trailers = JSON.parse(data);
}, function(err) {
// handle the error here and decide what should be put into movies[index].trailers
});
});
}, Promise.resolve()).then(function() {
return FileService.writeToJson(JSON.stringify(movies), config.showtimesfilepath);
});
});
从概念上讲,它所做的是调用movies.reduce()
,传入.reduce()
的起始值是一个已解析的承诺。然后,通过.reduce()
的每次迭代都会在承诺链上添加类似p=p的内容。然后(…)
。这将导致所有操作按顺序排列,等待一个操作完成后再调用下一个操作。然后,在.Then()
处理程序中,它返回MovieService.getContent()
承诺,以便此迭代也将等待内部承诺完成
您可能也可以并行执行这些操作,而无需强制对它们进行排序。您只需要知道它们何时全部完成,并且您需要保持所有数据的有序。可以这样做:
// in parallel
MovieService.getContent(config.url + '?key=' + config.moviekey).then(function(data) {
var movies = JSON.parse(data);
var promises = [];
movies.forEach(function(movie, index) {
var imdbid = movie.ids.imdb;
promises.push(MovieService.getContent(config.themoviedburl + 'tt' + imdbid + '/videos?api_key=' + config.themoviedbkey).then(function (data) {
movies[index].trailers = JSON.parse(data);
}, function(err) {
// handle the error here and decide what should be put into movies[index].trailers
}));
});
Promise.all(promises).then(function() {
return FileService.writeToJson(JSON.stringify(movies), config.showtimesfilepath);
});
});
或者,使用Bluebird的promise库的有用的promise.map()
,这里有一个较短的并行版本
// use Bluebird's Promise.map() to run in parallel
MovieService.getContent(config.url + '?key=' + config.moviekey).then(function(data) {
var movies = JSON.parse(data);
Promise.map(movies, function(movie, index) {
var imdbid = movie.ids.imdb;
return MovieService.getContent(config.themoviedburl + 'tt' + imdbid + '/videos?api_key=' + config.themoviedbkey).then(function (data) {
movies[index].trailers = JSON.parse(data);
}, function(err) {
// handle the error here and decide what should be put into movies[index].trailers
});
}).then(function() {
return FileService.writeToJson(JSON.stringify(movies), config.showtimesfilepath);
});
});
如果您希望在任何给定请求失败的情况下仍能继续此过程,那么您必须描述在这种情况下希望发生的情况,您可以通过处理
.getContent()
上的错误来实现这一点,以便它始终返回已解决的承诺。您可以异步运行承诺,而不是链接承诺,当所有承诺都得到解决时,无论其中是否有一个失败,您都可以使用文件服务写入JSON。这是通过使用
比如说,
MovieService.getContent(config.url + '?key=' + config.moviekey).then(function (data) {
var movies = JSON.parse(data);
var movieDataPromises = [];
movies.forEach(function (movie) {
var imdbid = movie.ids.imdb;
movieDataPromises.push(
MovieService.getContent(config.themoviedburl + 'tt' + imdbid + '/videos?api_key=' + config.themoviedbkey).then(function (trailerData) {
movie.trailers = JSON.parse(trailerData);
}).catch(function () {});
);
});
Promise.all(movieDataPromises).then(function () {
FileService.writeToJson(JSON.stringify(movies), config.showtimesfilepath);
});
});
在检索拖车信息时,存在带有空回调主体的catch的原因是我们希望阻止Promise.all()
执行其fail fast行为
编辑:避免使用。ahh是的,这是我的servicevar q=require('q');var请求=要求(“请求”);var kvikmyndir={getContent:function(url){var deferred=q.defer();请求(url,function(error,response,body){if(!error&&response.statusCode==200){deferred.resolve(body);}否则{deferred.reject(error);});返回deferred.promise;};module.exports=kvikmyndir;避开这个@Bergi-如果在检索电影预告片信息时
getContent()
中有任何拒绝,则Promise.all()
将立即使用拒绝值拒绝,同时放弃所有其他承诺。本例中的反模式通过在拒绝时进行解析来避免这种情况的发生,允许FileService.writeToJson()在Promise.all()中执行。这就是返回的内容。…catch(function(){/*ignore*/})
也可以,无需使用反模式。或者看看@Bergi-啊,是的!你说得对。谢谢。:)我已经更正了我的答案。Thx我很多时候都使用中间方法,但是如果一个或多个异步响应失败了怎么办,但是我仍然需要无规则地写入文件。处理这个问题最好的办法是什么@jfriend00@jonjonson-OP没有准确描述当其中一个请求中出现错误时他们想要做什么。正如我的回答所说,他们可以在.getContent()
上提供错误处理程序,并在那里提供他们想要的任何行为,因为在那里提供错误处理程序将“处理”那里的错误并防止其传播。我也在我的代码示例中添加了特定的信息。