如何在半异步情况下使用Javascript async/await? (例如在 String.replace 中)

问题描述 投票:0回答:1

例如,我正在对文本正文进行正则表达式替换:

  text = text.replace(re, function (match, comment, op1, op2, op3, op4, op5, op6, op7) {
    if (op1 !== undefined) {
      log("processing @@");
      parseEnum(config, op1, args1);
    } else if (op2 !== undefined) {
      log("processing {{}}");
      parseConfig(config, interpolateConfig(config, op2));
      return "";
    } else if (op3 !== undefined && !configOnly) {
      log("processing [[]]");
      return await parseMacro(config, op3, asyncInstances); // <---------- HERE
    } else if (op4 !== undefined) {
      log("processing <<>>");
      await parseInclude(config, interpolateConfig(config, op4)); // <---- HERE
      return "";
    } else if (op5 !== undefined && !configOnly) {
      log("processing ~~~~");
      // TODO parseStyle(op5);
    } else if (op6 !== undefined) {
      log("processing $$");
      return interpolateConfig(config, op6);
    } else if (op7 !== undefined) {
      log("processing ^^");
    }
  });

我需要这些替换发生同步每次调用替换函数都必须在下一次匹配和替换之前完成。然而,根据比赛的情况,有时我必须调用 async 函数。因此,为了保持同步,我决定使用 await。但要做到这一点,我还必须将匿名函数更改为异步:

  text = text.replace(re, async function (match, comment, op1, op2, op3, op4, op5, op6, op7) {
                          ++++++

不幸的是,String.replace 不接受异步函数。我在这个答案中找到了一个实用程序,可以做到这一点,从@ChrisMorgan的帖子中逐字复制:

async function replaceAsync(string, regexp, replacerFunction) {
    const replacements = await Promise.all(
        Array.from(string.matchAll(regexp),
            match => replacerFunction(...match)));
    let i = 0;
    return string.replace(regexp, () => replacements[i++]);
}

这样使用(省略未更改的代码)—

  text = await replaceAsync(
      text,
      re,
      async function (match, op1, args1, op2, op3, op4, op5, op6, op7) {
        ...
      }
  );

——它实际上似乎有效。我认为替换仍然会同步发生——也许这里更好的词是“顺序”——因为在幕后我们仍然一次调用 String.replace 。但后来我开始看到奇怪的结果,并意识到我错了。替换函数被并行调用,每当当前替换放弃控制时,“未来”替换就会开始处理(例如获取文件等,这就是某些函数异步的原因)。 我现在能看到的唯一方法是完全避免 async/await 并使用

Promise.resolve()

代替。但我试图在任何地方使用 async/await 以保持一致的风格。有没有另一种方法可以使用我没有看到的 async/await 来做到这一点? 更新:

嗯,我也不知道如何使用 Promise.resolve() 解决这个问题。我认为这本质上会像等待一样,但事实并非如此。

这样的东西应该有效
javascript replace async-await
1个回答
0
投票
async function x(text){ return text.replace(re, function (match, comment, op1, op2, op3, op4, op5, op6, op7) { if (op1 !== undefined) { log("processing @@"); parseEnum(config, op1, args1); } else if (op2 !== undefined) { log("processing {{}}"); parseConfig(config, interpolateConfig(config, op2)); return ""; } else if (op3 !== undefined && !configOnly) { log("processing [[]]"); return await parseMacro(config, op3, asyncInstances); // <---------- HERE } else if (op4 !== undefined) { log("processing <<>>"); await parseInclude(config, interpolateConfig(config, op4)); // <---- HERE return ""; } else if (op5 !== undefined && !configOnly) { log("processing ~~~~"); // TODO parseStyle(op5); } else if (op6 !== undefined) { log("processing $$"); return interpolateConfig(config, op6); } else if (op7 !== undefined) { log("processing ^^"); } }); } x(text).then((t)=>{ text = t; //run further code in here }) //code here will not have the replaced text

当 Promise 得到解决时,“then”将会被触发。
    

© www.soinside.com 2019 - 2024. All rights reserved.