带Promise的条件返回:throw vs returns null

时间:2016-03-23 07:48:25

标签: javascript promise

我发现自己编写了很多Promise代码来处理数据可能不可用的情况,并且我不确定在这种情况下是否传递null或throw / catch。

例如:

users.getById(id).then((user) => {
  if (!user) {
    return null;
  }
  return doSomething(user);
});

可以写成

users.getById(id).then((user) => {
  return doSomething(user);
}).catch((e) => {
  // User wasn't found
});

这些中的任何一种在某种程度上通常是优选的还是惯用的,还是最好在每种情况下都遵循我的直觉?

2 个答案:

答案 0 :(得分:2)

如果函数被调用users.getById,那么它的回调应该有一个用户对象,句点。获取用户对象的承诺仅在您实际获得用户对象时才会实现。

抛出typed Error instances表示各种错误情况。

users.getById(id).then((user) => {
    return doSomething(user);
}).catch((e) => {
    switch (e.Name) {
        case "UserNotFound":
            // User wasn't found
            break;
        default:
            // unexpected error
    }
});

bluebird承诺库有explicit support for typed exceptions并且单独support for catching operational errors,您可以模仿该行为。或者你可以使用蓝鸟:

users.getById(id).then((user) => {
    return doSomething(user);
}).error(UserNotFound, (e) => {
    // User wasn't found
}).catch((e) => {
    // unexpected error
});

答案 1 :(得分:1)

如果这是一个API调用,通常,您希望为使用者保存throw部分,而不是在内部处理它。

...或在内部处理convert-to-JSON部分,但如果存在加载错误或转换错误,请让外部世界使用oops。

这就是我的意思;我们将跳过承诺一秒钟:

function getData () {
  var data = null;
  try {
    data = getSomeData();
  } catch (e) { } // ignore it

  return data;
}


var data = getData();
var name = data.property.name; // BOOM

如果它会抛出,你应该抓住它(如果它没有抛出会更好,但更好的是要知道它会抛出,而不是知道)。

function getData () {
  var data = getSomeData();
  return data;
}


var data;
var name;
try {
  data = getData();
  name = data.property.name;
} catch (e) { /* now at the right level */ }

当然,投掷总体上并不是很好。根据你对函数式编程的立场,也不是空的。

如果我们做了一个返回承诺的电话:

function getData () {
  return callServer()
    .then( response => JSON.parse(response) );
}

getData()
  .then(showData)
  .catch(showError);

如果在内部处理了该错误,它将永远不会让最终用户处理他们的东西丢失的事实。如果您返回null,那么他们必须在null内进行各种then( ) - 检查。