Search code examples
javascriptasynchronousrequestfetch

How to access the request object in a fetch then/response function


I have a JavaScript loop iterating over an array. For every item, I perform a fetch request to insert the object. If the server response indicates it is an already inserted object, I try an update operation with another fetch call.

As the requests are asynchronous, the loop sets the request object to the next insert item before I try the update operation, so I end up requesting an update for an object it's not yet inserted.

Is there any way I can access the request object used for this fetch operation, so I can use that object instead of the loop var?

I've tried with this within the promise method, but it returns a reference to the window object: console.log(this) ==> > Window http://localhost

My code:

for (var i = 0; i < expectedRows; i++) {
    var row = myArray[i];
    customerCode = row['customer_code'];
    customerName = row['customer_name'];
    customerBalance = row['customer_balance'];
    // Build body call
    var callBody = {
        user: 'USER',
        code: customerCode,
        name: customerName,
        balance: customerBalance
    };
    var fetchOptions = {
        method: "POST",
        cache: "no-cache",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded",
        },
        redirect: "error",
        referrer: "ux-import", 
        body: JSON.stringify(callBody),
    };
    // Call
    var epurl = baseEP + '/customer/create';
    fetch(epurl, fetchOptions)
    .then(response => response.json())
    .then(response => {
        console.log(this) // <== Window object reference
        if (response.error === 0) {
            console.log('insert ok');
            insertRows++;
        } else {
            if (response.error == 2) {
                console.log('insert error => update');
                var updateEP = baseEP + '/customer/update';
                fetch(updateEP, fetchOptions) // <== Not what you expect 
                .then(updResponse => updResponse.json())
                .then(updResponse => {
                    if (updResponse.error === 0) {
                        console.log('update ok.')
                        updateRows++;
                    } else {
                        console.log('update error: ' + updResponse.msg)
                        errorMessages.push(updResponse.msg);
                    }
                })
                .catch(error => {
                    console.log('update failure');
                    errorMessages.push(error);
                });
            } else {
                console.log('insert error.');
                errorMessages.push(response.msg);
            }
        }
    })
    .catch(error => {
        console.log('insert failure.');
        errorMessages.push(error);
    });
}

I need some way to access this fetch call request object to achieve something like this:

var updFetchOptions = {
    method: "POST",
    cache: "no-cache",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
    },
    redirect: "error",
    referrer: "ux-import", 
    body: this.request.body, // this as a reference to this fetch's request
}
fetch(updateEP, updFetchOptions)...
:
:

Solution

  • Can you try this.

    for (let i = 0; i < expectedRows; i++) {
        let row = myArray[i];
        customerCode = row['customer_code'];
        customerName = row['customer_name'];
        customerBalance = row['customer_balance'];
        // Build body call
        let callBody = {
            user: 'USER',
            code: customerCode,
            name: customerName,
            balance: customerBalance
        };
        let fetchOptions = {
            method: "POST",
            cache: "no-cache",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            redirect: "error",
            referrer: "ux-import", 
            body: JSON.stringify(callBody),
        };
        // Call
        let epurl = baseEP + '/customer/create';
        fetch(epurl, fetchOptions)
        .then(response => response.json())
        .then(response => {
            console.log(this) // <== Window object reference
            if (response.error === 0) {
                console.log('insert ok');
                insertRows++;
            } else {
                if (response.error == 2) {
                    console.log('insert error => update');
                    let updateEP = baseEP + '/customer/update';
                    fetch(updateEP, fetchOptions) // <== Not what you expect 
                    .then(updResponse => updResponse.json())
                    .then(updResponse => {
                        if (updResponse.error === 0) {
                            console.log('update ok.')
                            updateRows++;
                        } else {
                            console.log('update error: ' + updResponse.msg)
                            errorMessages.push(updResponse.msg);
                        }
                    })
                    .catch(error => {
                        console.log('update failure');
                        errorMessages.push(error);
                    });
                } else {
                    console.log('insert error.');
                    errorMessages.push(response.msg);
                }
            }
        })
        .catch(error => {
            console.log('insert failure.');
            errorMessages.push(error);
        });
    }
    

    Basically, defining variables with var is not a good method as it doesn't maintain its state with each iteration of loop. But using let maintains the variable state for each iteration and you can use the variable even after doing some async task like fetch in your case.