我正在开发一个 Chrome 扩展,我需要使用 Chrome 消息从页面扩展代码与后台脚本联系。这为我的代码添加了相当程度的异步摆弄。一般目的是处理文本宏,即解析文本,使用存储在可从后台脚本访问的数据库中的数据。
在某些时候,我有:
findMacro(key)
.then(result => {
processMacro(key, result);
}};
处理器大致如下:
function processMacro(shortcut, text) {
text = macroBuilder(text);
}
macroBuilder
函数处理各种类型的宏,将处理过的文本推送到一个数组,然后运行 join('')。我的问题是,我需要支持嵌套的宏,当有这样的宏时,我再次调用 findMacro
,它在内部将 chrome sendMessage 发送到后台进程。处理器执行如下操作:
function macroBuilder(text) {
let pieces = [];
macroProcessorCode(text).forEach(res => {
res.visit({
text(txt, ctx) {
pieces.push(txt);
},
dates(obj, ctx) {
pieces.push(processDates(obj))
},
...
nested(obj,ctx) {
let fragments = [];
fragments.push(
findMacro(obj.name)
.then(res => {
return macroBuilder(res);
})
);
console.log('promised results:', fragments);
Promise.all(fragments)
.then(fragments => {
console.log('resolved results:', fragments);
pieces.push(fragments);
});
}
});
});
return pieces.join('');
}
出于某种原因,我的函数在解析之前返回,所以 promised results
发生在它返回之前,resolved results
发生在它返回之后。简而言之,在处理嵌套宏之前,我从代码处理文本返回结果。这只会发生在嵌套的情况下,其他类型的宏会被正确处理。
有什么想法吗?
最佳答案
macroBuilder
创建了一堆 promise ,但从不对它们做任何事情。相反,它需要等待它们并返回自己的 promise ,该 promise 将根据片段/片段的 promise 解决/拒绝。
这有点即兴,可能需要调整,但应该让您朝着正确的方向前进。见***
评论:
function macroBuilder(text) {
// *** An array for all the promises below
const piecePromises = [];
macroProcessorCode(text).forEach(res => {
res.visit({
text(txt, ctx) {
pieces.push(txt);
},
dates(obj, ctx) {
pieces.push(processDates(obj))
},
//...
nested(obj, ctx) {
let fragments = [];
fragments.push(
findMacro(obj.name)
.then(res => macroBuilder) // *** Note we can just pass `macroBuilder` directly
);
console.log('promised results:', fragments);
// *** Add this promise to the array
pieces.push(Promise.all(fragments)
// (*** This whole then handler can be removed
// once you don't need the logging anymore;
// just push the result of Promise.all)
.then(fragments => {
console.log('resolved results:', fragments);
return fragments;
})
);
}
});
});
// *** Wait for all of those and then join; ultimate result
// is a promise that resolves with the pieces joined together
return Promise.all(piecePromises).then(pieces => pieces.join(''));
}
此时,processMacro
没有太多意义;它看起来像这样(注意它返回一个 promise ):
function processMacro(shortcut, text) {
return macroBuilder(text);
}
...除非您使用未显示的快捷方式
执行某些操作。
假设您需要 processMacro
,如果您向调用者传播 promise ,您可以这样调用它:
return findMacro(key)
.then(result => processMacro(key, result));
...或者如果您不传播 promise ,则像这样:
findMacro(key)
.then(result => processMacro(key, result))
.catch(err => {
// Deal with the fact an error occurred
});
因为 promise 的规则之一是您要么传播 promise 要么处理它的错误。
关于javascript - 正确的 promise 链,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46539083/