【问题标题】:wrapping promise+then in new promise将 promise+then 包装在新的 promise 中
【发布时间】:2017-02-04 22:13:04
【问题描述】:

我有一个简单的承诺:

function p(l) {
  return new Promise(function(resolve) {
    alert(l);
    resolve();
  });
}

然后我尝试创建一个只有在 then 子句之后才会解决的承诺:

function pp(l1, l2) {
  return new Promise(function(resolve) {
    p(l1).then(() => {
      alert(l2);
      resolve();
    });
  });
}

我现在这样做:

p('start').then(pp('A', 'B')).then(p('end'));

我希望看到:开始,A,B,结束
但我看到的是:开始,A,结束,B

为什么?

我怎样才能实现我想要的,创建一个在 then 子句完成时将解决的 promise (pp)?

【问题讨论】:

  • .then(() => pp('A', 'B')) 将解决您的问题。详细解答。
  • 这会给你你想要的序列 p('start').then(p('A')).then(p('B')).then(p( 'End'));,但如果你有一个解决 nothing 的承诺,那就没有意义了。您可以对 alert('start');alert('A');alert('B');alert('end'); 执行相同的操作。有一个什么都解决不了的承诺真的没有意义。
  • coyotte508 - 不,这给了我:开始,结束,A,B
  • Hosar - 不,我不想更改代码的结构,这只是一个示例,我想创建一个带有 then 原因的承诺,然后可以将其链接为一个单元
  • 添加了工作演示

标签: es6-promise


【解决方案1】:

pp 可以更简单地编码:

function pp(l1, l2) {
  return p(l1).then(() => {
    alert(l2);
  });
}

这就是promise的重点,如果你每次都要写复杂的代码,那是不值得的:)

另外,.then 需要一个函数回调,其参数是前一个承诺/函数的返回值。

p('start').then(() => pp('A', 'B')).then(() => p('end'));

至于你有你的行为的确切原因,除了不使用.then 链接,因为它的意思是,我不太清楚为什么。

这段代码起作用的原因是,当在回调中返回Promise 时,Promise 被执行,它解析为的值作为参数传递给下一个回调。 () => pp('A', 'B') 等价于() => { return pp('A', 'B');}pp 在调用链的下一个回调之前被返回并等待。

如果您想保持相同的 .then 调用语法,则将 pp 更改为返回回调而不是 Promise 会起作用:

function pp(l1, l2) {
  return () => p(l1).then(() => {
    alert(l2);
  });
}

但是您不能再将其用作Promise。链接的最后一部分仍然需要更改:.then(() => p('end'))

【讨论】:

  • 谢谢!问题在于它将责任转移到顶层以正确的方式调用 pp (with () => pp('A', 'B') .. ) .. 这不是我想要的为了。我希望最上面的代码在不知道它有一个“then”子句的情况下链接它......你可以改变你的答案以将 return ()=> ... 移动到 pp 中,然后我会标记它
  • 怎么样:function pp(l1, l2) { return () => { p(l1).then(() => { alert(l2); }); }} ? (添加 {} )...这安全吗?那我还能用它作为承诺吗?
  • @kofifus 如果您添加{},您还需要添加returnfunction pp(l1, l2) { return () => { return p(l1).then(() => { alert(l2); });} ; }
  • 为什么?它没有回报就可以工作......也和你的解决方案一样吗?更安全吗?
  • @kofifus 它适用于这个特定的情况,适用于这个特定的引擎,但是如果你的承诺需要更长的时间,例如 ajax 代码的返回值,它就不会起作用。如果您不返回承诺,浏览器将不会等待它结束,不会将其解析值传递给下一个回调,并且接下来调用的代码都是未确定。它适用于这种特定情况是您的运气,但是如果您使用一些具有实际延迟的非阻塞代码而不是alert,则不会。
【解决方案2】:

在您的第二个函数中尝试以下操作

function pp(l1, l2) {
  return new Promise(function(resolve) {
    alert(l1);
    alert(l2);
    resolve();
  });
}

或者如果你想把p 函数放在pp 里面,那么

function pp(l1, l2) {
  return p(l1).then(() => {
    alert(l2);
  });
}



p('start').then(() => pp('A', 'B')).then(() => p('end'));

这里是演示https://plnkr.co/edit/fUisfcWrTu89xcc4j0cu?p=preview

【讨论】:

    【解决方案3】:

    来自mdn - “onFulfilled:当 Promise 实现时调用的函数。这个函数有一个参数,即实现值。”

    我的代码的问题在于,在 then(pp('A', 'B')) 中我传递了一个 value(pp() 的结果,这是一个承诺)而不是一个 函数(接收调用promise的实现值的函数)

    所以正确的使用 then 的方法是总是给它传递一个函数:

    function p(l) {
      return new Promise(function(resolve) {
        alert(l);
        resolve();
      })
    }
    
    
    function pp(l1, l2) {
      return p(l1).then(() => p(l2));
    }
    
    
    p('start').then(() => pp('A', 'B')).then(() => p('end'));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-31
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      相关资源
      最近更新 更多