繁体   English   中英

使用异步在Node JS中一个接一个地下载系列视频。

[英]Download videos in series one after the other in Node JS using async?

我要一个接一个地下载视频。

那就是第一个应该在第二个开始之前完全下载,而第二个应该在第三个开始之前完全下载,依此类推。

我有以下目录结构-

video-downloader
├── index.js
├── videos.js
├── package.json

package.json

{
  "name": "video-downloader",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "download": "^7.1.0"
  },
  "scripts": {
    "start": "node index"
  }
}

video.js

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',
  }
]

index.js

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`),
        )
    })
}

这会并行地逐块下载视频。 所有视频都立即下载,但没有一个在另一个开始之前完成。

如何串行下载?

我知道我应该使用http://caolan.github.io/async/之类的东西,但是它需要一个函数签名,而且我将videos作为数组,所以我不确定该怎么做。

您可以在标准的循环中使用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()

您可以将.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'); }) 

尝试异步等待。 首先下载,然后在同步中编写。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM