1

I did upload files after this I save the data of them in mongo but if I do with one file it's working but with loop/forEach/map/for not working anyway

loop of files

        await Promise.all(files.map(async (file) => {
           let url= await uploadFileAndSave(req, file);
            await saveFileDB(file,url);
        } ))

uploadFiles function Promise

    return new Promise(async (resolve, reject) => {
        let pathDir = req.params.uId + "/";
        let typeFolder = getTypeFolder(file.name);
        console.log("type", typeFolder);
        if (typeFolder) {
            pathDir += req.body.app ? req.body.app + "/" : "";
            pathDir += req.body.appId ? req.body.appId + "/" : "";
            pathDir += typeFolder + "/";
            currentPath = path.join(__dirname, "../uploads/", pathDir, Date.now() + "__" + file.name)
            console.log("currentPath", currentPath);
            file.mv(currentPath).then(async () => {
                console.log("sAAaved!!!", file.name);
                resolve(currentPath)
            })

        }
    })
}

save db function

saveFileDB = async (file, pathUrl) => {
 return new Promise(async(resolve, reject) => {
 let name = pathUrl.slice(pathUrl.lastIndexOf('/') + 1, pathUrl.length)
 let newFile = new fileModel({
     name,
     url: pathUrl,
     dateCreated: Date.now(),
     size: file.size / 1024 / 1024,
     icon: iconsClasses[file.name.split(".")[1]],
     delete: false,
 });
 // console.log("newFile",newFile);
 try {
     let result = await newFile.save();
     console.log("save in db", result);
 } catch (err) {
     console.log(err);
     res.send(err);
 }
   newFile.save((err, fileSaved) => {
     if (err){
       console.log("err",err);
       reject(err)}
       console.log('fileSaved',fileSaved);
     resolve(fileSaved)
   });
 })
}
  • The function that you pass to `files.map(..)` doesn't return anything. – Titus Oct 25 '20 at 15:45
  • 2
    What exactly is "not working"? Please describe the problem in more detail. Describe exactly what result you get and what result you want. – jfriend00 Oct 25 '20 at 15:48
  • 1
    @Titus it has an async callback so it returns an array of promises. – marzelin Oct 25 '20 at 15:50
  • if what you want from the loop is an array of saved files, you have to return the promise containing the file from `async` callback (or pull out the file from the promise and return it). Now, `Promise.all` just awaits (pauses the execution of the rest of the code) for saving to be done and returns an array of `undefined`. – marzelin Oct 25 '20 at 15:55
  • Your function to upload the file leaves the promise hanging forever if `typeFolder` is falsey. You should consider `... else if (!typeFolder) { reject(new Error('invalid type folder')); }` or something of the sort – Gershom Maes Oct 25 '20 at 16:24
  • [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! – Bergi Oct 25 '20 at 17:52
  • Why are you calling `newFile.save` twice? – Bergi Oct 25 '20 at 17:54

1 Answers1

1

Try to be clear whether you want a promise, or the resolved result

In your first code block, you are rightly intending to assemble a list of promises so that you can merge them with a Promise.all and then await the whole result, with the await.

However it seems to me that you are accidentally awaiting each promise individually inside the inner function (within the .map), so that the array being fed into Promise.all is no longer an array of promises.

Instead of this:

await Promise.all(files.map(
    async (file) => {
       let url= await uploadFileAndSave(req, file);
       await saveFileDB(file,url); 
       // This inner function "async (file) => ..." does not 
       // have a `return` statement, so it returns `undefined`, rather than 
       // the promise you intended to return. This is because you `await`ed 
       // the promise already, rather than `return`ing it to the outer loop.
    } 
))

I suggest this:

await Promise.all(files.map(
    async (file) => {
        let url= await uploadFileAndSave(req, file);
        return saveFileDB(file,url); 
        // Now the inner "async (file) =>" function returns
        // a promise (because that is the result type of saveFileDB)
    } 
))

As a stylistic issue, you may also want to change the "let url =" into a "const url=". Whenever you know that you are creating a variable whose value does not change until it is destroyed, it is helpful to mark it as a const. This helps readers and yourself when debugging (e.g. after the code gets longer), and also Javascript or even your code editor will warn you when you try to reassign it.

ProfDFrancis
  • 8,816
  • 1
  • 17
  • 26
  • Please can you create a new question showing explicitly the code you are now using? Remove all unnecessary code. Remove comments. Reduce it to exactly two files. Set the path names explicitly rather than through a series of string manipulations. And show exactly what error message you are getting. – ProfDFrancis Nov 11 '20 at 19:41