1

I have a code I was using inside Google GAS but I had to refactore it a bit to use it outside and I'm having trouble with a for loop I had to form an array. I'll make the code reproducible with read API Keys in a dev envirorment.

    
    const optionsGet = {
    'method': 'GET',
    'contentType': 'application/x-www-form-urlencoded;charset=UTF-8',
    'muteHttpExceptions': true,
};
    const website = 'https://atopems-desarrollo.com.ar';
    const ck = 'ck_112e7b278d5731d2cdb44a57c07bbeab2fc9196a';
    const cs = 'cs_e891f6cd193608f47f8acf340b985317448cdca4';
    var container = [];
    var surl = website + '/wp-json/wc/v3/products?consumer_key=' + ck + '&consumer_secret=' + cs + '&per_page=20' + '&orderby=id' + '&order=asc' + '&status=publish' + '&page=20';
    var url = surl
    console.log(url)


    var fetchCall = fetch(url, optionsGet)
        .then(response => {
            if (response.ok) {
                return response.json()
            } else {
                throw new Error('beep-boop no dio 200 OK' + response.status);
            }
            console.log(Error);
        })

    var total_pages = 40;
    var pages_count = 20;
    while (pages_count < total_pages) {
        pages_count++;
        fetchCall
            .then(data => {
                for (var i = 0; i < data.length; i++) {
                    //console.log(i);
                    container.push({
                        sku: data[i]['sku'],
                        id: data[i]['id'],
                        price: data[i]['price']
                    });
                }
            })
        console.log(container);
        var surl = website + '/wp-json/wc/v3/products?consumer_key=' + ck + '&consumer_secret=' + cs + '&per_page=20' + '&orderby=id' + '&order=asc' + '&status=publish' + '&page=' + (pages_count + 1);
        var url = surl
        console.log(url);
        var fetchCall = fetch(url, optionsGet)
            .then(response => {
                if (response.ok) {
                    return response.json()
                } else {
                    throw new Error('beep-boop no dio 200 OK' + response.status);
                }
                console.log(Error);
            })
    }

The code right now is in the snippet its functional. I can't figure out how to use fetch and get the data inside the while and to push with a for loop to an empty array. The following snippet is how I think it should work?

const optionsGet = {
        'method': 'GET',
        'contentType': 'application/x-www-form-urlencoded;charset=UTF-8',
        'muteHttpExceptions': true,
    };
        const website = 'https://atopems-desarrollo.com.ar';
        const ck = 'ck_112e7b278d5731d2cdb44a57c07bbeab2fc9196a';
        const cs = 'cs_e891f6cd193608f47f8acf340b985317448cdca4';
        var container = [];
        var surl = website + '/wp-json/wc/v3/products?consumer_key=' + ck + '&consumer_secret=' + cs + '&per_page=20' + '&orderby=id' + '&order=asc' + '&status=publish' + '&page=20';
        var url = surl
        console.log(url)


        var fetchCall = fetch(url, optionsGet)
            .then(response => {
                if (response.ok) {
                    return response.json()
                } else {
                    throw new Error('beep-boop no dio 200 OK' + response.status);
                }
                console.log(Error);
            })
        var preVal = [];
        var total_pages = 40;
        var pages_count = 20;
        while (pages_count < total_pages) {
            pages_count++;
            fetchCall
                .then(data => {
                  preVal.push(...data);
                })
            for (var i = 0; i < preVal.length; i++) {
                        //console.log(i);
                        container.push({
                            sku: preVal[i]['sku'],
                            id: preVal[i]['id'],
                            price: preVal[i]['price']
                        });
                    }    
            console.log(container);
            var surl = website + '/wp-json/wc/v3/products?consumer_key=' + ck + '&consumer_secret=' + cs + '&per_page=20' + '&orderby=id' + '&order=asc' + '&status=publish' + '&page=' + (pages_count + 1);
            var url = surl
            console.log(url);
            var fetchCall = fetch(url, optionsGet)
                .then(response => {
                    if (response.ok) {
                        return response.json()
                    } else {
                        throw new Error('beep-boop no dio 200 OK' + response.status);
                    }
                    console.log(Error);
                })
        }

But preVal would be empty since it would be filled by the time I try to do the for loop.

I'm pretty new to JS and programming in general. So far I've read some stuff about promises but I can't figure it out.

What I need is the for loop to work in creating a new array, since the rest of the code wants to use only those 3 values from the WC response.

Thank you.

vazcooo1
  • 181
  • 11
  • Was it intentional to share your working API keys? – Peter Pajchl Jan 27 '22 at 17:28
  • 1
    In general, you are mixing currently asynchronous and synchronous execution. E.g. `fetch` returns a `Promise` and is an async method. So you have 2 options A) either make sure code that must execute AFTER asynchronous call moves into `then` branch or B) rewrite things with `async/await` which will help you make the code "appear" more synchronous. – Peter Pajchl Jan 27 '22 at 17:33
  • @PeterPajchl yes, it's a testing site and they're read only. I guess I don't need it to be either async or synchronous. I'll read about async/wait, if not what would be to move after then? I could maybe call for all the data first in X function and then call it from another function to then proccess it? – vazcooo1 Jan 27 '22 at 17:42

1 Answers1

0

So, I solved the issue with the async / promise.

const ck = 'XXX'

const cs = 'XXX'

const website = 'XXX'

const optionsGet = {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'                   
                    }
                  };


async function batchWooUpdate() {
  gapi.client.sheets.spreadsheets.values.get({
    spreadsheetId: 'XXXXXXXXX',
    range: 'XXXXXXXXXX',  
  }).then(async function(response) {    
    var range = response.result;
    if (range.values.length > 0) {
            var surl = website + '/wp-json/wc/v3/products?consumer_key=' + ck + '&consumer_secret=' + cs + '&per_page=100' + '&orderby=id' + '&order=asc' + '&status=publish' + '&page=';
            var url = surl;
            var toUpdate = [];
            for (i = 0; i < range.values.length; i++) {
                    var row = range.values[i];
                    toUpdate.push({
                        sku: row[0],                        
                        price: row[1]
                    });
                  }
                  console.log(toUpdate);

            let allData = [];
            let morePagesAvailable = true;
            let total_pages = 300;
            let currentPage = 0;
            let container = [];
            while (morePagesAvailable) {
                currentPage++;
                const response = await fetch(`${url}${currentPage}`, optionsGet);
                let data = await response.json();
                morePagesAvailable = currentPage < total_pages;
                allData.push(...data);
            }
            for (var i = 0; i < allData.length; i++) {
                //console.log(i);
                container.push({
                    sku: allData[i]['sku'],
                    id: allData[i]['id'],
                    price: allData[i]['price']
                });
            }
            console.log(container);
            await console.log(allData);


            var data_obj = {}
            for (let obj of toUpdate)
                data_obj[isNaN(obj.sku) ? obj.sku.toUpperCase() : obj.sku] = {
                    'price': obj.price
                };

            console.log(data_obj);

            var container_obj = {}
            for (let obj of container)
                container_obj[isNaN(obj.sku) ? obj.sku.toUpperCase() : obj.sku] = {
                    'price': obj.price,
                    'id': obj.id
                };

            console.log(container_obj);

            var output = [];
            for (let sku in container_obj) {
                let data_subObj = data_obj[sku];
                let container_subObj = container_obj[sku];
                if (data_subObj && data_subObj.price != container_subObj.price) {
                    output.push({
                        'id': container_subObj.id,
                        'regular_price': data_subObj.price
                    });
                }
            }

            console.log(output);

            var temporary, chunk = 100;
            for (let i = 0; i < output.length; i += chunk) {
                temporary = output.slice(i, i + chunk);
                var payloadUp = {
                    update: temporary
                };

                console.log(payloadUp);

                var urlPost = website + '/wp-json/wc/v3/products/batch?consumer_key=' + ck + '&consumer_secret=' + cs;
                console.log(urlPost);
                let updateRes = await fetch(urlPost, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json;charset=utf-8'
                    },
                    body: JSON.stringify(payloadUp)
                });                
                let updateText = await updateRes.text();
                console.log(updateText);
            }
      } else {
      appendPre('No data found.');
    }
  }, function(response) {
    appendPre('Error: ' + response.result.error.message);
  });

This is using googles sheet API library.

My previous issue as pointed out by @Peter Pajchl

Was that fetch is in itself asynchronous and I wasn't letting the process finish (this is my rudimentary understanding).

So I did an async function and then used await in the fetch to let it finished and in the response.json(), using a simple while to paginate and pushing all the data from the fetches to an empty array outside the while loop. Then basically processing it.

I think my next step would be to do an array of promises and resolve them with Promise.all

But as of right now, it scares me a little.

vazcooo1
  • 181
  • 11