如何重构这个承诺回退?

时间:2016-06-14 19:33:23

标签: javascript promise refactoring ecmascript-6 es6-promise

这是一款经典的后备解决方案。如果第一个el没有被渲染,那么它会用其他渲染器重试它。如何最好地重构这个?

这段代码的错误在于:

  • 渲染器需要在一个数组中,但在这里,它们会在那些块中。
  • 当先前的渲染器不起作用时,它们需要落到另一个渲染器上
  • 第一个渲染器就像第二个渲染器和其他渲染器一样。它检查结果是否为空。那里有一个重复。但是,第一个需要先运行,第二个可以一起运行,只要其中一个返回结果就可以停止。
let first = $('#id1');

return this.render('priorityRenderer', first).then(isEmpty => {

  let els = [
    $('#id2'), $('#id3')
  ];

  if (isEmpty) {
    // put back the first el to the pool to render it again below
    els.unshift(first);
  }

  return Promise.all(els.map(el => {
    return this.render('secondaryRenderer', el)
      .then(result => {
        if (result) {
          return result;
        } else {
          return this.render('3thRenderer', el)
        }
      })
      .then(result => {
        if (result) {
          return result;
        } else {
          return this.render('4thRenderer', el)
        }
      })
      .then(result => {
        if (result) {
          return result;
        } else {
          return this.render('5thRenderer', el)
        }
      });
    })
});

1 个答案:

答案 0 :(得分:1)

您可以使用these approaches之一调用一系列渲染器,直到第一个返回结果:

renderers(rs, el, i=0) {
    if (i < rs.length)
        return this.render(rs[i], el).then(result => result || this.renderers(rs, el, i+1));
    else
        return Promise.reject(new Error("no renderer worked, tried: "+rs));
}

然后在你的方法中,你可以做

let first = $('#id1');
let els = [$('#id2'), $('#id3')];
let rs = ['secondaryRenderer', '3rdRenderer', '4thRenderer', '5thRenderer'];

return Promise.all([
    this.renderers(['priorityRenderer'].concat(rs), first)
].concat(els.map(el =>
    this.renderers(rs, el)
)));