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 存在很大不一致的情况下更改它。
在 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 存在很大不一致的情况下更改它。