我试图更新数据库中的一堆记录,基于业余爱好网站的IMDB结果来学习Node和React。我对async / await代码和承诺相当新,所以我很难挣扎。
根据我所阅读的内容,此代码应该:
相反,我得到以下控制台信息:
[0] Executing (default): SELECT `id`, `rank`, `name`, `IMDBId`, `rating`, `genre`, `posterUrl`, `createdAt`, `updatedAt`, `reviewerId`, `yearId` FROM `TopMovies` AS `TopMovie`;
[0] Movie count: 150
[0] All done
[0] Updated movie: Chef
[0] Executing (default): UPDATE `TopMovies` SET `rating`=3.5,`genre`='Adventure',`posterUrl`='https://images-na.ssl-images-amazon.com/images/M/MV5BMTY5NTYzNTA1M15BMl5BanBnXkFtZTgwODIwODU1MTE@._V1_UY268_CR0,0,182,268_AL_.jpg',`updatedAt`='2018-02-02 19:49:17.036 +00:00' WHERE `id` = 44
[0] Updated movie: The Champions
[0] Executing (default): UPDATE `TopMovies` SET `rating`=4.5,`genre`='10 October 2015 (USA) ',`posterUrl`='https://images-na.ssl-images-amazon.com/images/M/MV5BMTk5MjM2MjQ4MF5BMl5BanBnXkFtZTgwNjIxMDA5NzE@._V1_UX182_CR0,0,182,268_AL_.jpg',`updatedAt`='2018-02-02 19:49:17.092 +00:00' WHERE `id` = 87
[0] Updated movie: Trance
请注意,它在输出"全部完成"后更新记录,并从app.get()函数返回。理想情况下它会更像:
[0] Executing (default): SELECT `id`, `rank`, `name`, `IMDBId`, `rating`, `genre`, `posterUrl`, `createdAt`, `updatedAt`, `reviewerId`, `yearId` FROM `TopMovies` AS `TopMovie`;
[0] Movie count: 150
[0] Updated movie: Chef
[0] Executing (default): UPDATE `TopMovies` SET `rating`=3.5,`genre`='Adventure',`posterUrl`='https://images-na.ssl-images-amazon.com/images/M/MV5BMTY5NTYzNTA1M15BMl5BanBnXkFtZTgwODIwODU1MTE@._V1_UY268_CR0,0,182,268_AL_.jpg',`updatedAt`='2018-02-02 19:49:17.036 +00:00' WHERE `id` = 44
[0] Updated movie: The Champions
[0] Executing (default): UPDATE `TopMovies` SET `rating`=4.5,`genre`='10 October 2015 (USA) ',`posterUrl`='https://images-na.ssl-images-amazon.com/images/M/MV5BMTk5MjM2MjQ4MF5BMl5BanBnXkFtZTgwNjIxMDA5NzE@._V1_UX182_CR0,0,182,268_AL_.jpg',`updatedAt`='2018-02-02 19:49:17.092 +00:00' WHERE `id` = 87
[0] Updated movie: Trance
[0] All done
* Returns from app.get
我做错了什么,这使得它说'#34;所有完成"在它处理任何记录之前?这是相关代码:
const imdb = require('imdb');
const _require = require('./models/index'),
Year = _require.Year,
Reviewer = _require.Reviewer,
TopMovie = _require.TopMovie,
ViewStat = _require.ViewStat,
Op = _require.Sequelize.Op;
app.get('/imdb_import', (req, res) => {
const UpdateMovies = async () => {
const topMovies = await TopMovie.findAll();
console.log("Movie count: " + _.size(topMovies));
// await topMovies.forEach(async topMovie => {
// await updateMovieDetails(topMovie);
// });
await Promise.all(topMovies.map(async(topMovie) => {
await updateMovieDetails(topMovie);
}));
console.log("All done");
return topMovies;
};
const updateMovieDetails = topMovie => {
return imdb(topMovie.get('IMDBId'), (err, data) => {
if (err) {
console.log(err.stack);
}
if (data) {
topMovie.posterUrl = data.poster;
topMovie.rating = Math.round(data.rating) / 2;
if (data.genre) {
topMovie.genre = data.genre[0];
}
topMovie.save();
console.log("Updated movie: " + topMovie.name);
}
});
};
UpdateMovies()
.then((data) => res.status(200).json(data))
.catch(error => console.log(error));
});
此项目的代码可以在这里找到,async_imdb'分支:https://github.com/mandreko/ov_stats/tree/async_imdb如果有人想在本地运行它
答案 0 :(得分:5)
await updateMovieDetails(topMovie);
在此代码中没有完成任何操作。请记住,await
不会阻止包含函数完成并返回一个promise。它只影响函数内的代码。
因此,如果您希望使用它来对您的操作进行排序,那么它就不会这样做。此外,由于您未从.map()
回调中退回任何内容,因此updateMovieDetails(topMovie)
的承诺无法返回Promise.all()
,因此不会等待它们。
改变这个:
await Promise.all(topMovies.map(async(topMovie) => {
await updateMovieDetails(topMovie);
}));
到此:
await Promise.all(topMovies.map((topMovie) => {
return updateMovieDetails(topMovie);
}));
然后,Promise.all()
将等待所有updateMovieDetails()
次来电完成。
此外,updateMovieDetails()
不会返回与其活动相关联的承诺,因此对Promise.all()
执行任何操作都无法完成任务。
您可以手动宣传imbdb()
函数,然后从中返回生成的承诺:
const util = require('util');
// make promsified version of imdb()
const imdbPromise = util.promisify(imdb);
const updateMovieDetails = topMovie => {
return imdbPromise(topMovie.get('IMDBId')).then(data => {
if (data) {
topMovie.posterUrl = data.poster;
topMovie.rating = Math.round(data.rating) / 2;
if (data.genre) {
topMovie.genre = data.genre[0];
}
console.log("Updated movie: " + topMovie.name);
topMovie.save();
}
});
};
以下是我推荐的积累:
const util = require('util');
// make promsified version of imdb()
const imdbPromise = util.promisify(imdb);
app.get('/imdb_import', (req, res) => {
const UpdateMovies = async () => {
const topMovies = await TopMovie.findAll();
console.log("Movie count: " + _.size(topMovies));
await Promise.all(topMovies.map(updateMovieDetails);
console.log("All done");
return topMovies;
};
const updateMovieDetails = topMovie => {
return imdbPromise(topMovie.get('IMDBId')).then(data => {
if (data) {
topMovie.posterUrl = data.poster;
topMovie.rating = Math.round(data.rating) / 2;
if (data.genre) {
topMovie.genre = data.genre[0];
}
console.log("Updated movie: " + topMovie.name);
return topMovie.save();
}
});
};
UpdateMovies()
.then((data) => res.status(200).json(data))
.catch(error => console.log(error));
});