简体   繁体   中英

How to make multiple calls to the same function fire in order, when function includes asynchronous actions

I'm dealing with a race condition, and trying to sort out how to solve it.

I've got multiple pieces of code that call the same function. This function calls fetch on an API endpoint and makes DOM modifications according to the result. The function may be called on page load, or in response to user action. The user may trigger the function call multiple times.

Things get broken if the DOM modification for a later call happens before a modification from an earlier call, which occasionally happens.

Is there a common pattern for ensuring that these DOM modifications occur in order, even if the fetch calls do not?

I'm thinking creating some sort of a queue, where I add a timestamped row to an array when the method is called, and then attach the fetch results to that row when fetch completes, then make all the DOM modifications down the list of timestamps until I hit a row without a result. Does that make sense or is there an off the shelf solution or common pattern I'm missing here?

function getContent() {
    fetch(url)
        .then((response)) => modifyDOM(); // Make this part run in sequence.
}

// for reasons not shown here, the first call takes so long that the second one
// completes its DOM modification first. This race condition breaks my content.
getContent();
getContent(); 

You can keep track of a persistent Promise that gets reassigned to the new request when the function is called:

let prom = Promise.resolve();
function getContent() {
    const promToReturn = prom
      .then(() => fetch(url))
      .then(modifyDOM);
    // continue the chain even if there's an error during one of them
    prom = promToReturn.catch(() => undefined);
    // while returning the original Promise whose results and errors can be seen outside
    return promToReturn;
}

This way, only one request will be going on at any one time, at most. Sequential calls to getContent only result in one ongoing request at a time. getContent(); getContent(); will result in one request, which finishes and modifies the DOM, and then after that's done, another request that then modifies the DOM.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM