Wilson Teo
Wilson Teo

Reputation: 83

For loop in promise function

I have below functions that I am trying to use an async function to check if an item Id was already added into a grid. But, I am stuck at the for loop "processFindCode" function, it always returns false. How to make the checking routine work and continue to addItem function?

My objective,

1. a loop up event pass in selected array values
2. get needed info array via web api 
3. process each of array item
4. validate if the item.Id_item_code already exists in detail grid, if not add a new item into the grid

sorry for the lengthy code, I am considered new to js. please also advise the best way to achieve my objective.

Thank in advance

               var theList = this.value;
           if (theList == "") {
               return true;
            }

            // Set up aysnc promise function
            async function processAPIResult() {
                let result; 
                let promises = []; //setup a promises aray
                // Loop thru Lookup selections
                // results store in the promises aray 
                theList.split(',').forEach(function (kId, k) {
                    promises.push(make_api_call(kId));
                })
                result = await Promise.all(promises); // async await
                return result; 
            }
            // Call API Function
            function make_api_call(id) {
                return ($.get(ew.API_URL + "GetQuotationDetail/" + encodeURIComponent(id)));
            }

            function delay() {                   
                return new Promise(resolve => setTimeout(resolve, 300));
            }

            async function addItem(kcode) {
                var ridx = $("#key_count_fs_invoicedtlgrid")[0].value; // get actual table row
                //  Get serices information from API
                var tQty = 1;
                if (ridx == 1 && $("#x1_Id_item_code")[0].value == "") {
                    $("#x" + ridx + "_Id_item_code").value(kcode);
                    $("#x" + ridx + "_qty").value(tQty);

                    $("#x" + ridx + "_Id_item_code").select();
                    $("#x" + ridx + "_Id_item_code").change();

                    //$("#x" + ridx + "_Id_quotattoindetl").value(Id_quotationDetail); // store quotation detail Id
                } else {
                    // 2nd row onward
                    // when it is available but it it is not empty, create a new row
                    if (typeof $("#x" + ridx + "_Id_item_code") === 'undefined' || $("#x" + ridx + "_Id_item_code")[0] != "") {
                        ew.addGridRow('#tbl_s_invoicedtlgrid');
                    }
                    ridx = $("#key_count_fs_invoicedtlgrid")[0].value;
                    var c_part_code = $("#x" + ridx + "_Id_item_code")[0];
                    var c_qty = $("#x" + ridx + "_qty")[0];

                    c_part_code.value = kcode;
                    c_qty.value = fmtDecimal(tQty, 'qty');
                    $("#x" + ridx + "_Id_item_code").select();
                    $("#x" + ridx + "_Id_item_code").change();

                    //$("#x" + ridx + "_Id_quotattoindetl").value(Id_quotationDetail); // store quotation detail Id

                    // trigger onChange to updateAmount() function;
                    $("#x" + ridx + "_qty").change();
                }
            }

            async function processFindCode(code) {
                found = false;
                var rCnt = $("#key_count_fs_invoicedtlgrid")[0].value;
                for (j = 1; j < rCnt + 1; j++) {
                    // loop thru row and col
                    if ($("#x" + j + "_item_code").val() != null) {
                        if ($("#x" + j + "_item_code").val() == kcode) {
                            if ($("#x" + j + "_item_code")[0].style.display != "none") { // visible row only. Deleted row's display is set to hidden.
                                found = true;
                            }
                            break; // exit loop column
                        }
                    }
                    if (found) {
                        break; // exit loop row
                    }

                } // end for loop rCnt
                isFound = found;
                return isFound;
            }

            async function processItemCode(code) {
                // notice that we can await a function
                // that returns a promise                   
                let isFound = await processFindCode(code);
                await delay();
                if (!isFound) {
                    await addItem(code);
                }
                console.log('Done! ' + code);
                //await delay();
                //console.log(item.Id_item_code);
            }

            async function processAPIitem(item) {
                for (const itm of item) {
                    await processItemCode(itm.Id_item_code);                         
                }
                //console.log('Done! '+ apiitem.Id_item_code);
            }

            // main async task to get results
            //-------------------------------
            async function doTask() {
                //get result form API function
                let result = await processAPIResult();
                //process each API array
                for (const item of result) {
                     await processAPIitem([item]);
                }
            }

            doTask();

Upvotes: 0

Views: 71

Answers (1)

Roamer-1888
Roamer-1888

Reputation: 19288

Simple answer: $item_code.hide() hides; it isn't a test. Use $item_code.is(':visible') instead.

function processFindCode(code) {
    var found = false;
    var rCnt = $('#key_count_fs_invoicedtlgrid').val();
    for (var j=1; j<rCnt+1; j++) {
        if ($('#x' + j + '_item_code').val() != null) {
            if ($('#x' + j + '_item_code').val() == code) {
                if ($('#x' + j + '_item_code').is(':visible')) {
                    found = true;
                    break;
                }
            }
        }
    }
    return found;
}

Longer answer: Finding the desired element with $('#x' + j + '_item_code') is inefficient especially when performed three times. You can improve matters by leveraging the power of javascript/jQuery and write something like this.

function processFindCode(code) {
    var $rows = $('#tbl_s_invoicedtlgrid tbody tr'); // select all table rows in the table's tbody (assumed selector) .
    return $rows.get().reduce(function(bool, row) {
        return bool || $("id*='_item_code'", row).filter(':visible').filter(function() {
            return this.value === code;
        }).length > 0;
    }, false);
}

This is still not as efficient as it could be. The "id*='_item_code'" selector is pretty nasty but at least it only applies to one row at a time, not the whole DOM.

For vastly improved efficiency, give the item_code element class="item_code" and select with $(".item_code", row). The addItem() function would benefit greatly from the same approach.

Upvotes: 1

Related Questions