javascript - 正确的 promise 链

标签 javascript asynchronous promise

我正在开发一个 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/

相关文章:

javascript - 在 JavaScript 节点环境中将 Gzip 内容编码响应转换为 JSON 数据

Javascript嵌套For循环在返回数组时不更新数组

c# - WCF 服务 : Asynchronous method or BackgroundWorker

javascript - 使用 Node-MySQL 时 ES6 Promise 乱序

html - 如何在单击单选按钮后在固定的时间间隔内禁用它们

javascript - Skycons,不能两次显示相同的图标吗?

javascript - jQuery 和 "hash"有问题吗?

c# - 异步读写器储物柜

javascript - 防止 ES6 promise 吞下错误(不使用 .catch)

promise - 如何让一个 JavaScript 库兼容多个 Promise 库?