【问题标题】:Unable to get promises to work, subsequent promises not being called无法让承诺生效,后续的承诺不会被调用
【发布时间】:2016-07-18 16:29:58
【问题描述】:

我正在尝试用额外的承诺来扩展一些现有的代码,但它们目前对我来说是一个新话题,我显然遗漏了一些东西。这是作为 npm 构建脚本的一部分运行的。

我目前想要实现的只是在每个架构发生打包操作后调用 final。我试过把它包装在一个

return new Promise

但目前我没有从该函数返回任何内容,所以我不确定我应该在最后的解析调用中包含什么。如果我只是用真正的方法调用resolve,什么都没有发生,并且将它包装在一个promise中似乎会导致函数实际上没有运行,并且在任何地方都没有发现任何错误?

我猜我完全错了,我想要实现的只是在前一个函数完成后运行另一个函数?

这是我无法调用的附加代码。

function build(cfg) {
  return new Promise((resolve, reject) => {
    webpack(cfg, (err, stats) => {
      if (err) return reject(err);
      resolve(stats);
    });
  });
}

function startPack() {
  console.log('start pack...');
  build(electronCfg)
    .then(() => build(cfg))
    .then(() => del('release'))
    .then(paths => {
      if (shouldBuildAll) {
        // build for all platforms
        const archs = ['ia32', 'x64'];
        const platforms = ['linux', 'win32', 'darwin'];

        platforms.forEach(plat => {
          archs.forEach(arch => {
            pack(plat, arch, log(plat, arch));
          });
        });
      } else {
        // build for current platform only
        pack(os.platform(), os.arch(), log(os.platform(), os.arch()));
      }
    })
    .then(() => {
      console.log('then!');
    })
    .catch(err => {
      console.error(err);
    });
}

function pack(plat, arch, cb) {
  // there is no darwin ia32 electron
  if (plat === 'darwin' && arch === 'ia32') return;

  const iconObj = {
    icon: DEFAULT_OPTS.icon + (() => {
      let extension = '.png';
      if (plat === 'darwin') {
        extension = '.icns';
      } else if (plat === 'win32') {
        extension = '.ico';
      }
      return extension;
    })()
  };

  const opts = Object.assign({}, DEFAULT_OPTS, iconObj, {
    platform: plat,
    arch,
    prune: true,
    'app-version': pkg.version || DEFAULT_OPTS.version,
    out: `release/${plat}-${arch}`,
    'osx-sign': true
  });

  packager(opts, cb);
}

【问题讨论】:

  • cfg 在这里是未定义的变量 .then(() => build(cfg)) 并且应该在严格模式下导致拒绝。应该是then((cfg) => build(cfg))。这可能有意义,也可能没有意义,如果webpack 应该根据自己的结果被调用两次,这是另一个问题。
  • 感谢您的快速回复,cfg 是在文件的更深处定义的,因为它就在这里运行良好,我无法实现的是最终的 .then 被调用?跨度>
  • 我看不出这段代码有什么问题。倒数第二个.then 甚至不是异步的(不返回承诺),因此您甚至不需要另一个.then 来扩展此代码,如所写(但它应该可以工作)。我建议你重新验证你的假设。
  • 您应该看到“那么!”在打包发生之前几乎立即输出。我现在看到pack 需要回调cb,所以我怀疑你希望它等待所有这些完成?如果是这样,那么除非你让pack 也返回一个承诺,否则这不会发生。

标签: javascript node.js ecmascript-6 es6-promise


【解决方案1】:

你没有说log 是什么,但如果它是一个普通的日志记录函数,那么看起来你正在将undefined(调用log(...) 的结果)作为cb 参数传递给pack。也许你的意思是:

pack(plat, arch, () => log(plat, arch));

在任何情况下,等待打包完成都不会做任何事情。我不知道为什么您没有看到任何控制台输出,但如果您希望在所有打包完成后发生此输出,那么您需要将 packager 包装在一个承诺中。比如:

var pack = (plat, arch) => new Promise(resolve => {
    // ...
    packager(opts, resolve);
});

然后使用Promise.all 而不是forEach 进行所有打包(如果可以的话,可以并行):

.then(paths => {
  if (!shouldBuildAll) {
    return pack(os.platform(), os.arch());
  }
  return Promise.all(['linux', 'win32', 'darwin'].map(plat =>
      Promise.all(['ia32', 'x64'].map(arch => pack(plat, arch))));
})
.then(() => console.log('then!'))
.catch(err => console.error(err));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    相关资源
    最近更新 更多