Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 当使用嵌套承诺时,如何避免意大利面代码?_Design Patterns_Promise - Fatal编程技术网

Design patterns 当使用嵌套承诺时,如何避免意大利面代码?

Design patterns 当使用嵌套承诺时,如何避免意大利面代码?,design-patterns,promise,Design Patterns,Promise,假设您有6个返回承诺的方法,A()、B()、C()、D()、E()、F()和G() 其中一些在其他人完成之前无法正确执行。例如,C()需要一个()。F()&E()需要C()。B()需要A()和F()。G()要求所有其他项都是完整的 A().then(() => { C().then(() => { F().then(() => { B(); }); E(); }); }).then(() => { G(); }); D();

假设您有6个返回承诺的方法,A()、B()、C()、D()、E()、F()和G()

其中一些在其他人完成之前无法正确执行。例如,C()需要一个()。F()&E()需要C()。B()需要A()和F()。G()要求所有其他项都是完整的

A().then(() => {
  C().then(() => {
    F().then(() => {
      B();
    });
    E();
  });
}).then(() => {
  G();
});
D();
现在,假设需要在几个影响其行为的函数之间运行一些逻辑

A().then(() => {
  let foop = this._service.getFoop();
  C(foop).then((noop) => {
    noop.forEach((n) => { n *= -1; });
    F(noop).then((boop) => {
      boop = boop.flatten();
      B(foop, boop);
    });
    E('MonkeyWrench');
  });
}).then(() => {
  let glipglop = this._service.findGlip(this.LOCAL_GLOP_KEY);
  G(glipglop, 42);
});
D();
然后,最重要的是,我们需要确保每个承诺都能捕捉并处理错误

A().then(() => {
  let foop = this._service.getFoop();
  C(foop).then((noop) => {
    noop.forEach((n) => { n *= -1; });
    F(noop).then((boop) => {
      boop = boop.flatten();
      B(foop, boop).catch((e) => {
        this.handleErrorB(e);
      });;
    }).catch((e) => {
      this.handleErrorF(e);
    });
    E('MonkeyWrench').catch((e) => {
      this.handleErrorE(e);
    });
  }).catch((e) => {
    this.handleErrorC(e);
  });
}).then(() => {
  let glipglop = _service.findGlip(this.LOCAL_GLOP_KEY);
  G(glipglop, 42);
}).catch((e) => {
  this.handleErrorA(e);
});
D().catch((e) => {
  this.handleErrorD(e);
});
所以现在我们有了一个由承诺组成的完整的异步程序——它看起来像一团乱麻

什么样的方法可以让这样的程序更容易阅读,以便将来的贡献者可以避免 跳进意大利面代码?嵌套的承诺结构是否天生混乱,或者是否存在可接受的协议 整理一下,让它更可读

我读过,它有一些好主意,比如使用promise.all([…]) 一次运行多个承诺,但它不支持在嵌套的承诺调用之间具有逻辑

提前感谢任何愿意在这方面为我传授一些智慧的人。

这些作品在承诺调用之间的逻辑性特别好-只需为新的价值创造一个新的承诺

var a = A();
var foop = a.then(() => this._service.getFoop());
var c = foop.then(C);
var noop = c.then(x => x.map(n => n * -1));
var f = noop.then(F);
var boop = f.then(x => x.flatten());
var b = Promise.all([boop, foop]).spread(B);
var e = Promise.all([boop, foop]).then(() => E('MonkeyWrench'));
var d = D();
var glipglop = Promise.all([d, e, f]).then(() =>
  this._service.findGlip(this.LOCAL_GLOP_KEY));
return Promise.all([gliplop, 42]).spread(G);
您可以将错误处理程序添加到相应的承诺中

所以现在我们有了一个由承诺组成的完整的异步程序——它看起来像一团乱麻


这不是因为承诺,而是因为你的控制流程一团糟。也许这是内在的复杂性,但很可能不是。尝试将部分逻辑分解成单独的函数——无可否认,这种策略在嵌套闭包模式下更有效。还要尽量避免副作用——需要在并发控制流中的特定时间运行并影响其他功能的逻辑总是混乱的。相反,要尽可能纯粹地只处理沿流传递的不可变值。

您真的想并行运行它们吗?看起来您忘记了几个
return
s。您的错误处理程序实际上是做什么的?是否要在它们之后继续流(因为供应默认结果等)?您是否希望他们不仅处理具有相应名称的函数所承诺的结果中的错误,而且处理链接到它们的处理程序中的错误?请发布您的真实代码。在不破坏你的逻辑的情况下,很难看出有什么可以改进。这个方法可以用来解决这个烂摊子…@Jordão你能试着在回答中说明这一点吗?我认为在这里应用它不会带来很多好处。