1

I need to download images from the array of links to them like this https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png

And there is the code I wrote. I used https://www.npmjs.com/package/image-downloader

const download = require('image-downloader');
const links = require('./links.json');

var options = {
  url: "",
  dest: links.dest,
};

  links.url.forEach((link) => {
    options.url = link
   download
    .image(options)
    .then((result) => {
      console.log("Image downloaded", result);
    })
    .catch((error) => console.log("downloaded error", error));
  });

And the .json file

{
"url":[
"https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
"https://api.time.com/wp-content/uploads/2019/08/better-smartphone-photos.jpg",
"https://iso.500px.com/wp-content/uploads/2016/03/stock-photo-142984111.jpg",
]
"dest":"D:/"
}

But because it works async, all the downloaded images are unordered, not like in the list of links (it can`t be sorted by the date). How can I modify this code to make it download images in ordered way?

Drakon4k
  • 11
  • 1
  • Why not use the response headers to set the date of the file you write to disk? – Brad Jan 24 '21 at 02:27
  • Why do you care what order the downloads complete in? If you want to be able to correlate the completed download to the original link, that's available in `link` within the scope of the callback. – jarmod Mar 10 '21 at 00:55

5 Answers5

0

Check this out: Creating a promise chain in a for loop

Your image downloader uses JS Promises to download the images, so what you want to do is instead of calling 3 promises you are looking to chain the promises using a for loop. In order to do so, follow the example in the Stack Overflow answer and ditch your .forEach loop for a regular for loop.

Da Mahdi03
  • 1,468
  • 1
  • 9
  • 18
0

use async/await to synchronously loop over your list, and use the following function to do it

Edit: use async/await or use Promise.all when using javascript to not block the javascript event loop.

const asyncForEach = async (array, callback) => {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}

var options = {
  url: "",
  dest: links.dest,
}

// use it like so:
await asyncForEach(links.url, async link => {
  try {
    options.url = link
    const result = await download.image(options)
    console.log("Image downloaded", result)
  } catch (err) {
    console.error(err)
  }
})
alilland
  • 2,039
  • 1
  • 21
  • 42
0

Use Promise.all - it resolves when every promise in an array of promises resolves, and returns an array of all the results in the original order! I recommend you avoid using a for loop here, as that will download images in series when they can be much more efficiently downloaded in parallel!

let download = require('image-downloader');
let links = require('./links.json');

let options = { url: '', dest: links.dest };

let allLinksDownloadedPromise = Promise.all(links.url.map(link => {
  return download.image({ ...options, link });
}));

allLinksDownloadedPromise.then(arrayOfDownloads => console.log('Downloaded:', arrayOfDownloads));
Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
0

Make it simple with for-loop and async/await syntax.

const download = require('image-downloader');
const links = require('./links.json');

(async () => { // `await` can only be used inside an async function.
  try {
    for (const url of links.url) {
      // wait until downloading process finish then continue to solve next url
      const result = await download.image({ url, dest: links.dest });
      console.log("Image downloaded", result);
    }
    console.log("Done!");
  } catch(error) {
    console.log("downloaded error", error)
  }
})();
hoangdv
  • 15,138
  • 4
  • 27
  • 48
0

The image-downloader works with promises internally.

const download = require("image-downloader");
const { resolve } = require("path");    

const jsonFile = require("./tbc02.json");

jsonFile.map((item) => {
  const options = {
    url: `https://bookplace.com${item["image-src"]}`,
    dest: resolve(`./images/${item.title}.jpg`),
  };

  download
    .image(options)
    .then(({ filename }) => {
      console.log("Saved to", filename);
    })
    .catch((err) => console.error({ err }));
});

And

//tbc02.json
[
    {
        "image-src": "/media/6456f90974455632b530ea.jpg",
        "title": "Psychomotor and Creative",
    },
    {
        "image-src": "/media/29b0970dbd13e5e1bee.jpg",
        "title": "Maths Workbook",
    }
]
Youzef
  • 616
  • 1
  • 6
  • 23