Node.js:为什么 Braintree 方法通过错误响应解决承诺?

Node.js: Why Braintree methods resolve promise with error response?

在 Braintree Node.js SDK 中,如果没有给出回调,这些方法将 return 一个承诺。例如:

第一次

gateway.customer.create({
        firstName: "First",
        lastName: "Last",
        email: "test@abc.com",
        id: "123123"
    })
    .then((response) => {
        console.log(response); // correct response from this line
    })
    .catch((err) => {
        console.error(err);
    });

它将正确记录响应。

之后,我再次执行相同的代码。我预计会因为重复的自定义 ID 而失败。

第二次

gateway.customer.create({
        firstName: "First",
        lastName: "Last",
        email: "test@abc.com",
        id: "123123"
    })
    .then((response) => {
        console.log(response); // error response from this line
    })
    .catch((err) => {
        console.error(err);
    });

它将在 then 块中记录错误响应。

第三次

gateway.customer.find("1231234") // not existing
    .then((response) => {
        console.log(response);
    })
    .catch((err) => {
        console.error(err); // error from this line
    });

它将记录 catch 块中的 Not Found

为什么第二个给出 resolve 错误而第三个给出 reject?如果我写一个 promifier 并将所有使用 success: false 的响应视为 reject 是否安全?

这个答案来自github,完美的说明了问题。 https://github.com/braintree/braintree_node/issues/130#issuecomment-370079910

不同服务器 SDK 使用的 Braintree 底层 API 遵循结果对象模式。

因此,如果您的交易成功,您将获得:

gateway.transaction.sale({
  amount: '5.00',
  paymentMethodNonce: 'fake-valid-nonce',
  options: {
    submitForSettlement: true
  }
}).then((result) => {
  // result.success === true
  // result.transaction is the transaction object
})

现在,假设您有一笔交易被处理器拒绝:

gateway.transaction.sale({
  // sandbox amount to trigger processor declined 
  // https://developers.braintreepayments.com/reference/general/testing/node#test-amounts
  amount: '2000.00', 
  paymentMethodNonce: 'fake-valid-nonce',
  options: {
    submitForSettlement: true
  }
}).then((result) => {
  // result.success === false
  // result.transaction is still the transaction object
})

在这种情况下,即使交易失败,交易对象仍然会被创建,所以承诺解决了,但报告销售不成功是有道理的。

只有少数情况下 promise 会实际拒绝。一种是如果无法访问 Braintree 网关(没有互联网,revoked/incorrect API 密钥,速率限制):

braintree.transaction.sale(saleOptions).catch((err) => {
  // you'll get here because the Braintree gateway could not be reached
  // or the API keys are invalid
  // or there have been too many requests made, etc
});

或者找不到资源:

gateway.transaction.find('bad-id').catch((err) => {
  // this will result in a not found error
});

基本上在所有其他情况下,承诺将以 result.success 是真还是假来解决。

此模式非常适用于交易,即使交易实际上并未向客户收费,您也需要尝试交易的记录。对于您给出的示例,它的效果不太好:

braintree.clientToken.generate({ customerId: 'invalid' }).then((res) => {
  // res.sucess === false
  // res.message === 'Customer specified by customer_id does not exist',
});

没有创建底层对象。

我认为我们使用这种模式主要是因为其他 Braintree 服务器 SDK 使用这种模式。其他 SDK 使用这种模式的原因是因为替代方案是让 SDK 在事务失败的情况下引发异常(因为这些语言没有与节点相同的异步模式,所以你实际上必须抛出一个如果请求失败则出错)。

我同意这种模式并不完美,但现在我们无法在没有主要版本升级和与其他服​​务器 sdk 存在很大不一致的情况下更改它。