0

I am trying to read a file using the fs library then replace some elements after an iteration then return the composed string However, the function returns undefined

function concatproduce(order, producestring) {
    if (order.cart.produce[0].productid != null) {
        order.cart.produce.forEach((element, index) => {
            if (!element.delstatus) {
                element.delstatus = 'Pending';
            }
            fs.readFile('controllers/ordercartitemtemplate.html', 'utf8', function(err, data) {
                if (err) {
                    return console.log('lima' + err);
                }
                //console.log(data)
                producestring += (data
                    .replace('//Filename//', element.imageURL)
                    .replace('//Prodname//', element.producename)
                    .replace('//Quantity//', element.quantity)
                    .replace('//Price//', element.price)
                    .replace('//Total//', element.total)
                    .replace('//Delstatus//', element.delstatus));
            });
        });
        return producestring;
    }
}
Steve Nginyo
  • 303
  • 3
  • 12
  • `fs.readFile` is asynchronous. So, the callback of `fs.readFile` will not invoke before the `return producestring` is executed that why it always returns undefined. I advise you take time to watch this https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf or https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – ttquang1063750 Dec 07 '20 at 06:10

1 Answers1

-1

Maybe this will help you, I changed the asynchronous file read operation to a synchronous one and also replaced the forEach with reduce

The function iterates through each of the produce elements using .reduce, refer to the documentation link provided. The readFileAsync is used to make it easy to handle the result of the file read and assign it to the producestring after each iteration.

function concatproduce(order, producestring) {
    if (order.cart.produce[0].productid != null) {
        return order.cart.produce.reduce((producestring, element) => {
            if (!element.delstatus) {
                element.delstatus = 'Pending';
            }
            try {
                const data = fs.readFileSync('controllers/ordercartitemtemplate.html', 'utf8')
                producestring += (data
                    .replace('//Filename//', element.imageURL)
                    .replace('//Prodname//', element.producename)
                    .replace('//Quantity//', element.quantity)
                    .replace('//Price//', element.price)
                    .replace('//Total//', element.total)
                    .replace('//Delstatus//', element.delstatus));
                    return producestring;
            } catch (err) {
                console.log('lima' + err);
                return producestring;
            }
        }, producestring);
    }
}
kgangadhar
  • 4,886
  • 5
  • 36
  • 54
  • You are a life saver... I want to understand your function though... this is like an iteration that returns a value after every iteration?? and then concatenates it to the one in the previous iteration... Did I understand this right?? – Steve Nginyo Dec 07 '20 at 06:31
  • I updated the answer, Let me know if you need any help. – kgangadhar Dec 07 '20 at 13:53
  • I just added an explanation with links in the above answer. The method remains the same. – kgangadhar Dec 11 '20 at 06:01
  • Thank you. I will go through the video again but this function worked. – Steve Nginyo Dec 11 '20 at 06:52