Currently, I have a while loop that uploads files to cloudinary. Cloudinary gives you the data in a function. I want replace the value of each local file with the URL which that can be done inside the function. But when you try to access the same data outside the function, it is still the old value (e.g. kitten-playing.gif instead of https://res.cloudinary.com/aboutdavid/image/upload/v1605242001/samples/animals/kitten-playing.gif). So, how can you set data in a function and keep it that way outside the function?
const cheerio = require("cheerio");
const fs = require("fs");
const cloudinary = require("cloudinary").v2;
const $ = cheerio.load(
'<img src="kitten-playing.gif"><img src="accessories-bag.jpg"><img src="sample.jpg">'
);
for (let i = 0; i < $("img").length; i++) {
if (fs.existsSync($("img")[i].attribs.src)) {
cloudinary.uploader.upload($("img")[i].attribs.src, function(
error,
result
) {
$("img")[i].attribs.src = result.url;
console.log(`In function (${i}): ${$("img")[i].attribs.src}`)
// https://res.cloudinary.com/aboutdavid/image/upload/v1605242001/samples/animals/kitten-playing.gif
});
console.log(`Out function (${i}): ${$("img")[i].attribs.src}`)
// kitten-playing.gif
}
}
Edit: That’s really all it is supposed to do, change the src local paths to URLs
I’ve got a feeling this is just a callback order-of-operations thing.
Look at your DevTools Console. I suspect you’ll see them paired like Out... In instead of In...Out because the ‘Out’ log line runs first, so your code is doing what you want, but the logs are tricking you.
Callbacks happen when they happen. You can’t read down through the code file and assume that’s the order of execution
Use the DevTools element inspector to check the src of the images after the function runs. Or make a button that prints out all of the img srcs at a time of your choosing.
Oh, I forgot t mention this is Node.js and Cheerio. I honestly this using the document function would be a lot easier but I can’t
But yes,
that is right:
Out function (0): kitten-playing.gif
Out function (1): accessories-bag.jpg
Out function (2): sample.jpg
In function (2): http://res.cloudinary.com/aboutdavid/image/upload/v1605274932/rjhutiwjlupqkpcuw5rw.jpg
In function (1): http://res.cloudinary.com/aboutdavid/image/upload/v1605274932/m2eaf5f2ayynqc5xpjfv.jpg
In function (0): http://res.cloudinary.com/aboutdavid/image/upload/v1605274932/oqdompfkgxao7wnlnbal.gif
Ok, so reading between the lines, your problem is that all of this happens in a server route handler, and the response going back to the client still has the original URLs?
If that’s the case, it would be good to see more of the code to advise you on the architecture.
But, broadly, you have two readily available choices:
Do the response.send from within the cloudinary callback
Add an argument to the function you posted above which is itself a callback, and execute that within the cloudinary callback.