使用promises编写可读代码的最佳方法是什么?

时间:2016-02-01 17:43:39

标签: javascript node.js promise

我有一些看起来像这样的node.js承诺代码:

function myFunc(data) {
  Q(data).then(function(data) {
    return getPromise1(globalVar).then(function(res1a) {
      return getPromise2(JSON.parse(param2)).then(function(res2a) {
        return doStuff();
      }).then(function(res2b) {
        return getPromise3(data).then(function(res3a) {
          return getPromise4.then(function(res4a) {
            // more stuff
          })
        })
      })
    })
  })
})

如您所见,此代码不易读取。有更好的方法吗?

3 个答案:

答案 0 :(得分:3)

如果您不需要同时获得所有结果,请停止处理回调等承诺:

function myFunc(data) {
  Q(data).then(function(data) {
    return getPromise1(globalVar);
  }).then(function(res1a) {
    return getPromise2(JSON.parse(param2));
  }).then(function(res2a) {
    return doStuff();
  }).then(function(res2b) {
    return getPromise3(data);
  }).then(function(res3a) {
    return getPromise4;
  }).then(function(res4a) {
    // more stuff
  })
})

如果你这样做,那么你可以尝试coroutines给定生成器函数支持(Q可能有一些东西,但这里是Bluebird方式):

var myFunc = bluebird.coroutine(function* myFunc(data) {
  var res1a = yield getPromise1(globalVar);
  var res2a = yield getPromise2(JSON.parse(param2));
  var res2b = yield doStuff();
  var res3a = yield getPromise3(data);
  var res4a = yield getPromise4;

  // more stuff
})

synchronous inspection

function myFunc(data) {
  var res1a = getPromise1(globalVar);
  var res2a = res1a.then(function() {
    yield getPromise2(JSON.parse(param2));
  });
  var res2b = res2a.then(function() {
    // feel free to use res1a.value() here;
    // you know that it has to have been resolved
    doStuff();
  });

  // …

  return res4a;
}

答案 1 :(得分:1)

在您的示例中,使用lambda表达式会有所帮助:

Q(data) .then(data => getPromise1(globalVar) .then(re1a => getPromise2(JSON.parse(param2)

等等。 没有嵌套和这种风格,它看起来不像回调地狱:)

答案 2 :(得分:1)

除了将数据参数与控制流参数分离之外,承诺的目标之一实际上是解决这个巨大的三角形代码块问题。

function myFunc(data) {
  Q(data).then(function(data) {
    return getPromise1(globalVar);
  }).then(function(res1a) {
    return getPromise2(JSON.parse(param2));
  }).then(function(res2a) {
    return doStuff();
  }).then(function(res2b) {
    return getPromise3(data);
  }).then(function(res3a) {
    return getPromise4;
  }).then(function(res4a) {
    // more stuff
  })
}

现在,您需要嵌套一个promise的唯一原因是,如果您需要使用函数中的promise返回的数据,而不是紧跟在它之后。见下文:

doAsyncA().then(function(x) {
  doAsyncB().then(function(y) {
    doSyncUsingBothReturns(x, y);
  })
})