[英]Download videos in series one after the other in Node JS using async?
I want to download videos one after the other in a series. 我要一个接一个地下载视频。
That is the first one should be completely downloaded before the second one starts & the second one should be completely downloaded before the third one starts & so on. 那就是第一个应该在第二个开始之前完全下载,而第二个应该在第三个开始之前完全下载,依此类推。
I have the following directory structure - 我有以下目录结构-
video-downloader
├── index.js
├── videos.js
├── package.json
{
"name": "video-downloader",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"download": "^7.1.0"
},
"scripts": {
"start": "node index"
}
}
const videos = [
{
url: 'https://video.com/lesson1.mp4',
name: 'Lesson 1',
},
{
url: 'https://video.com/lesson2.mp4',
name: 'Lesson 2',
},
.
.
.
{
url: 'https://video.com/lesson2.mp4',
name: 'Lesson 100',
}
]
const fs = require('fs')
const download = require('download')
const videos = require('./videos')
const OUTPUT_DIR = 'Downloads'
fs.mkdir(OUTPUT_DIR, () => {
main()
})
const main = () => {
videos.map((video, i) => {
console.log(`Downloaded file ${i + 1} of ${videos.length} (${video.name})`)
download(video.url).pipe(
fs.createWriteStream(`${OUTPUT_DIR}/${video.name}.mp4`),
)
})
}
This downloads videos chunk by chunk parallelly. 这会并行地逐块下载视频。 All the videos are downloaded at once but none of them gets completed before the other one starts.
所有视频都立即下载,但没有一个在另一个开始之前完成。
How do I download it serially? 如何串行下载?
I know I should use something like http://caolan.github.io/async/ but it needs a function signature & I have videos
as an array so I'm not sure how to go about it. 我知道我应该使用http://caolan.github.io/async/之类的东西,但是它需要一个函数签名,而且我将
videos
作为数组,所以我不确定该怎么做。
You can use the await
keyword on standard for loops, and things will process in order, and wait on each download before proceeding. 您可以在标准的循环中使用
await
关键字,事情将按顺序进行,并在每次下载之前等待,然后继续。
const fs = require('fs')
const download = require('download')
const videos = require('./videos')
const util = require('util')
const mkdirAsync = util.promisify(fs.mkdir)
const OUTPUT_DIR = 'Downloads'
const main = async () => {
await mkdirAsync(OUTPUT_DIR)
for (let i = 0; i < videos.length; i++) {
const video = videos[i]
const data = await download(video.url)
fs.writeFileSync(`${OUTPUT_DIR}/${video.name}.mp4`, data)
console.log(`Downloaded file ${i + 1} of ${videos.length} (${video.name})`)
}
}
main()
You can use .reduce
with promises to resolve sequentially, as follows: 您可以将
.reduce
与promise一起使用以进行顺序解析,如下所示:
const fs = require('fs') const sh = require('shelljs') const download = require('download') const videos = require('./videos') const OUTPUT_DIR = 'Downloads' sh.mkdir('-p', OUTPUT_DIR) videos = videos.reduce((acc, item) => { return acc.then(() => { return new Promise((resolve) => { // Here you are using it as a Duplex Stream, not a promise, // therefore, you must check when the stream emits the 'end' event // so you can proceed further let stream = download(video.url) .pipe(fs.createWriteStream(`${OUTPUT_DIR}/${video.name}.mp4`)); stream.on('end', () => { console.log(`stream done ${item}`); resolve(item); }) }) }); }, Promise.resolve()); // 'videos' is now a promise videos.then((lastPromise) => { // using reduce will return the last evaluated item(promise) // but reaching the last one means the promises before that have been resolved console.log('all files were downloaded'); })
Try async await for this. 尝试异步等待。 First download and then write in Sync.
首先下载,然后在同步中编写。
const fs = require('fs');
const sh = require('shelljs');
const download = require('download');
const videos = require('./videos');
const OUTPUT_DIR = 'Downloads';
sh.mkdir('-p', OUTPUT_DIR);
videos.forEach(async (video, i) => {
console.log(`Downloading ${video.name}. Fil${i + 1}/${videos.length} - `);
const data = await download(video.url);
fs.writeFileSync(`${OUTPUT_DIR}/${video.name}.mp4`, data);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.