Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using await with replaceAll's callback function

I am trying out a Chrome extension.

How do I get a replaceAll‘s callback function to use await ?

window.onload = async () =>
{
    const elem = document.getElementById('#myID');
    const elem_modified = elem.replaceAll(regex, await myFunction);
    document.getElementById('#myID').innerHTML = elem_modified;
}

myFunction :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const myFunction = async (str) =>
{
    const items = [...str.matchAll(regex)][0];

    // Do some manipulation

    let amount = number * value;

    const amount_modified = await calculate(amount);

    console.log("amount_modified = " + amount_modified); // This shows correctly

    return items[0] + ' (' + amount_modified + ')';
}

The result is like

over [object Promise] to many people

>Solution :

You don’t, replaceAll — like lots of functions that support callbacks — doesn’t expect a promise as a return value from the callback. In the vast majority of cases, you can’t usefully pass a promise to code that doesn’t expect one. (map is one exception to that rule.)

You haven’t provided a runnable example or an example of your regular expression, but the general shape of the solution here will be:

  1. Split the string into parts (the segments you want to pass through your async function and the segments between them).
  2. Start the calculation for each of the segments you want to process and get a promise (from your async function) of the result; for the segments in-between, just create a promise fulfilled to the original segment value.
  3. Wait for all of those to complete by using Promise.all, awaiting the promise it provides. (That’s assuming it’s okay to start processing all the segments at once, rather than waiting for the processing of one to end before starting processing the next.)
  4. Assemble a new string from the updated segments and the segments that used to be between them.

Here’s a rough sketch that isolates the numbers in a string and builds a new string with the numbers doubled. This version doesn’t, of course, need to be async at all, but you can substitute a truly async operation for calculate:

async function calculate(str) {
    await new Promise((resolve) => setTimeout(resolve, 10)); // Just so we do actually do something async
    return str ? String(Number(str) * 2) : str;
}
async function example(str) {
    const rex1 = /(\d+)/; // Note the capture group, so `split` retains the delimiter between matches
    const rex2 = /^\d+$/; // Same as above, but full string match and no capture group
    // #1
    const parts = str.split(rex1);
    // #2 and #3 (the `await`)
    const updated = await Promise.all(parts.map(async (part) => {
        if (rex2.test(part)) {
            return await calculate(part);
        }
        return part;
    }));
    // #4
    return updated.join("");
}

example("Testing 1 2 3 testing")
.then((result) => console.log(result))
.catch((error) => console.error(error));

Side note: The DOM event system won’t pay any attention to the promise the async function you’re using as an event handler returns, so it’s important not to allow any errors (promise rejections) to terminate that handler, since those rejections will be unhandled.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading