javascript - 多个异步调用回调

标签 javascript asynchronous es6-promise

我在多个异步调用方面遇到问题。我有三项任务想要申请。首先我从第一个请求中获取一些 json 数据。然后,当该请求完成时,我从另一个服务发出多个请求以获取电影预告片,并将该数据合并到第一个响应中的每个对象。当所有这些都完成后,我想将该数据写入 json 文件。很简单,但我没有兑现 promise 。

这是我的代码

    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);
    };
});

现在这可以工作了,但是如果循环中的一个请求失败怎么办?那么我的计数器不正确,我会将数据写入文件。有人可以帮我使用 promise 来设置类似的场景吗?哦,是的,我的代码的另一个亮点是 MovieService 女巫发出所有请求

最佳答案

使用 Promise 对数组上的一系列操作进行排序的常见方法是使用 .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() 的起始值是一个已解决的 promise 。然后,通过 .reduce() 的每次迭代都会使用 p = p.then(...) 之类的内容添加到 Promise 链中。这会导致所有操作按顺序排列,等待一个操作完成后再调用下一个操作。然后,在该 .then() 处理程序内部,它返回 MovieService.getContent() Promise,以便此迭代也将等待内部 Promise 完成。

<小时/>

您也可以并行执行这些操作,而无需强制它们按顺序排列。您只需要知道它们何时完成,并且需要保持所有数据有序。可以这样做:

// 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() 上的错误来实现 这样它总是返回一个已解决的 promise 。

关于javascript - 多个异步调用回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34253855/

相关文章:

c# - 如何从头开始实现异步 I/O 绑定(bind)操作?

c# - 秒表计时异步/等待方法不准确

asynchronous - 使 TcpListener 异步处理连接的正确方法是什么?

javascript - 从另一个函数中的 Promise 内部返回一个值

javascript - Angular 2 和 C# API - 未处理的 Promise 拒绝 : ReferenceError: _body is not defined

javascript - 如何关闭由 document.createElement 创建的元素?

javascript - 为什么我的复制粘贴 Bootstrap 灯箱不起作用?

javascript - 使用ES6的顺序迭代Promise

promise - Javascript Promise 解析方法在控制台中打印。如何?

javascript - 从 ‘demo’ key 更改为我的 key 后,无法填充 EON 图表