#Reusing Queries in a for or a map loop

1 messages · Page 1 of 1 (latest)

sacred tree
#

I was trying to run this function but it didn't work. I used map and forEach and the same result. I don't have an error, just run but apparently don't iterate. ShowAlert doesn't show the message either.

Maybe I am doing something wrong . I'm storing the parameters using storeValue and the run the function. Basically is an invoice detail insert.

fnMaptest: async() => {
let loline = await tblShopifyOrders.selectedRow.line_items.map(line => ( {...line}) );
await loline.map((line) => {
storeValue('loShopifyInvoiceDetailsParameters',{invoice_uq: '7AE4F1DC', itemId: line.product_id, qty: line.quantity, price: line.price, saleman_uq: '7667B2FE', notes: 'TEST'});

showAlert(line.product_id)

fnInsertShopifyInvoiceDetails.run()
}
)
return
}

Thank you for your help,

Carlos

upbeat oakBOT
#

Hi There!
Thanks for reaching out to us. One of our engineers will be with you shortly.

If you are stuck with an issue/error, please help us with following information.

  1. Which version of Appsmith are you on?
  2. Provide screenshots/screen recordings of the original error/code snippet.
  3. Add details about your use case and provide steps to reproduce the issue, if
    possible.
upbeat oakBOT
#

Hi Carlos! The map() methods creates an array. Could you please try to use a
for loop? Also, please make sure to await the query runs and the storeValue()
methods. Here is our documentation about JS promises:
https://docs.appsmith.com/core-concepts/writing-code/javascript-promises

Previously, the only way to achieve asynchronous workflows in Appsmith was through callbacks, and dealing with callbacks was not easy. Appsmith now supports native JavaScript promises to make working with asynchronous workflows easier.

sacred tree
#

fnMaptest2: async() => {

                    const    loline = await tblShopifyOrders.selectedRow.line_items.map(line  => ( {...line}) );
    
                    const calls = await  loline.forEach( line => async() => {
                                    await storeValue('loShopifyInvoiceDetailsParameters', {invoice_uq: '7AE4F1DC', itemId: line.product_id, qty: line.quantity, price: line.price, saleman_uq: '7667B2FE', notes: ''} );
                                    
                                    await showAlert(line.product_id)
                                    
                                    await fnInsertShopifyInvoiceDetails.run()
                                                                        }
                                                    )

                    // Wait for all to finish (or any to reject).
                    return Promise.all(calls)
                                .then(() => showAlert('Promise.all - All successful'))
                                .catch(() => showAlert('Promise.all - Something went wrong'))
                                .finally(() => showAlert('Promise.all - finished'))
}
#

This is the Editor and don't show any error

#

This is the button that runs the function

upbeat oakBOT
#

We'll need some time to check this and get back to you.

upbeat oakBOT
#

Hi there.
It's a bit tricky to figure out what's going on here.
It's not showing any error because the syntax of your code is correct.
However, it's possible the code is doing something other than what you wanted.
Let's take it few steps at a time

#

const calls = await loline.forEach((line) => async () => {}

For this line, you're using an async function within a forEach call. The way the
javascript runtime handles forEach calls, it won't wait for the code within the
block to finish executing before moving on to the next thing.
I would advice that you don't make asynchronous calls within your forEach block.

Secondly, I think you're supposed to use a map here instead of a forEach.
forEach is just to iterate and doesn't do anything. Map however creates an array
of values returned from each iteration.

Lastly, You are putting the code that's supposed to be executed in your forEach
call inside another function that is not getting called. In the end, your
"calls" variable will contain an empty array, hence, why you're not getting any
response

#

Overall, please carefully take a look at your code again and see if you can fix
these things on your end. The issue is 100% mixup in semantics.

To better understand the differences between a forEach and map iteration,
checkout this resource
https://www.geeksforgeeks.org/difference-between-foreach-and-map-loop-in-javascript/

sacred tree
#

Thank you for the suggestions

#

I wrote the code in this way:

#

fnMaptest3: async() => {

    let myArray = tblShopifyOrders.selectedRow.line_items.map(line  => ( {...line}) );
  //return myArray
const returnValue = myArray.map((element) => {
                showAlert(element.price)
                 storeValue('loShopifyInvoiceDetailsParameters', {invoice_uq: '7AE4F1DC', itemId: element.product_id, qty: element.quantity, price: element.price, saleman_uq: '7667B2FE', notes: ''} )
            .then(fnInsertShopifyInvoiceDetails.run());
    return  {ID: element.product_id, Price: element.price, Qty: element.quantity};

})
return Promise.all(returnValue)
                                .then(() => showAlert('Promise.all - All successful'))
                                .catch(() => showAlert('Promise.all - Something went wrong'))
                                .finally(() => showAlert('Promise.all - finished'))
}
#

it works for the first iteration, but not in the second apparently it doesn't have time to change store the parameters. If I run the function several times it can execute the query for the second line

#

I suppose is because I can't use await

#

If I add Async() and await there is no error but the function don't works

#

maybe there is another way to do this

upbeat oakBOT
#

Hi there.
I love what you've done for the refactoring. Job well done!

The last part i would love you to pay attention to is the use of Promise.all()
First of all, you need to use await with promise.all() calls (i.e await
Promise.all()). Using then.catch doesn't really cut it for me because it makes
the syntax a bit weird for a return value.

Secondly, the parameter to be parsed to a Promise.all() call has to be
asynchronous function call.
For examples, say you have 2 asynchronous function calls in your code like so:

const func1 = async () => {}
const func2 = async() => {}

you can use await and promise.all() to execute both like so:
await Promise.all([func1(), func2()])

In your case, the reason your code is not working is because you're parsing
array of objects to Promise.all() instead of array of asynchronous functions.

sacred tree
#

Thank you for your help. I change the code but now I have an error and code go directly to catch

#

You said that the reason my code is not working is because I'm parsing an array of objects instead of an array of asynchronous functions

#

How I do that apparently I did something wrong

#

and again thank you for your help but I am trying to have this code as a model for my other workflows

upbeat oakBOT
#

Hi there!
Looking at the recent screenshot you sent, I don't think it will work as you
intend.
Also, I don't think i understand what you're trying to achieve with the codebase
so, it's a bit tricky to tell you what to do.

So that i can better help you, can you explain to me what you're trying to
achieve within the fnMaptest3 function as clearly as possible?

sacred tree
#

Thank you. The idea is to execute an store procedure to insert invoices lines

#

the first part of this flow is generate the Invoice header once the invoice header is inserted then we ran this process to insert the lines

#

the invoice header and invoice details comes from an invoice in Shopify

#

I have this process running in another app with the same store procedures but it was created with c#

#

now I am creating a different app and one of the modules is ecommerce and we have to interact with Shopify and Woo Commerce using rest API

#

in this page we can see the invoice header, invoice lines and customer info we got from Shopify with the API

#

we need to upload those invoices in our system

#

once we have there we interact with other modules like inventory and procurant

#

when the fulfilment is ready we can generate labels with other API and then update the fulfilment state with other API

#

I can create the invoices headers and the first line with no problem but when iterate the second line and so on we have the problem because the function runs before the parameters are iterated

#

so only get the first one

#

I captured the messages and is very clear the error. The parameters are iterated before the function runs. So the store procedure, in this case, is executed twice with the same parameter, the last one.

#

I want to have clear this flow because I will reuse in other iterations. Most of the process I only to executed one line at a time so is not important iterate, but this flows are a different thing.

upbeat oakBOT
sacred tree
#

Hi

#

at the contrary thank you for your help I know you are attending a lot of issues at same time

#

I do the same job with my customers

#

finally I've created the function in different way with out use map or foreach

#

just iterating with a for loop

#

this is the code:

upbeat oakBOT
#

You're a genius!
I would love to see how you were able to do that. Maybe I could learn a thing or
2 from it.

Overall, thank you for your understanding.
Feel free to reach out when you have other issues. We're always happy to help.

sacred tree
upbeat oakBOT
#

Thank you very much.
I'll go through it when I get the chance.

sacred tree
#

When you press the bottom send Invoices to Flexy it runs that code and upload the invoice and details in that way we have our ERP integrated with Shopify the same with the product stock and product prices we run a function to update the prices and stock from our ERP in Shopify