例如,我正在对一段文本进行RegExp替换:
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
功能。因此,为了保持同步,我决定使用
等待
。但要做到这一点,我还必须将匿名函数更改为async:
text = text.replace(re, async function (match, comment, op1, op2, op3, op4, op5, op6, op7) {
++++++
然而,遗憾的是,String.replace不接受异步函数。我找到了
this answer
一个用于实现这一点的实用程序,由@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()来解决这个问题。我原以为这基本上就像在等待,但事实并非如此。