node.js api接口
by Roger Jin
罗杰·金(Roger Jin)
There are two facts of life: you breathe air, and errors will occur in your programs.
生活有两个事实:呼吸空气,程序中会发生错误。
We’ve all experienced trouble connecting to Wi-Fi, or had a phone call drop on us abruptly. Intermittent failures across internet works are statistically unusual on the whole, but still bound to occur. This means that for programmers, anything that waits for a response over a network is prone to error.
我们所有人在连接Wi-Fi时都遇到了麻烦,或者突然打了个电话。 从统计上看,跨互联网工作的间歇性故障在总体上是不寻常的,但仍会发生。 这意味着对于程序员来说,任何等待通过网络响应的内容都容易出错。
I’m an architect for a “content management system as a service” called ButterCMS, so I’ll explore reliability using this tool. It consists of:
我是一个名为ButterCMS的“内容管理系统即服务”的架构师 ,因此我将使用此工具探索可靠性。 它包括:
The database, logic, and administrative dashboard is a service through a web API. The question is “What can you do with the inevitable errors in your Node.js client?” Errors over a client API are bound to happen–it is what you do about it that matters most.
数据库,逻辑和管理仪表板是通过Web API提供的服务。 问题是“您如何处理Node.js客户端中不可避免的错误?” 客户端API上的错误注定会发生-最重要的是您所要做的。
In this article I’ll walk through how I added better handling of failures to the ButterCMS JavaScript API client. By the end of this article, you will hopefully have a better understanding of how to deal with failure in your own API clients.
在本文中,我将逐步介绍如何为ButterCMS JavaScript API客户端添加更好的故障处理方法。 到本文结尾,希望您对如何处理自己的API客户端中的故障有更好的了解。
To begin, let’s look at an example API request for retrieving a blog post from the Butter API:
首先,让我们看一个示例API请求,该请求从Butter API中检索博客文章:
butter.post.retrieve('example-post') .then(function onSuccess(resp) { console.log(resp.data); });
This will work except it leaves you blind to any exceptions the client can throw at you. Note the client API uses promises to get blog data. Keep this in mind as JavaScript takes on a new dimension through promises.
这将起作用,除了它使您对客户端可能向您抛出的任何异常视而不见。 注意,客户端API使用promise获取博客数据。 请记住这一点,因为JavaScript通过Promise开辟了一个新的维度。
To handle exceptions using a promise, slap a catch()
at the end.
要使用Promise处理异常,请在最后拍一拍catch()
。
For example:
例如:
butter.post.retrieve('example-post') .catch(function onError(error) { console.log(error); });
Done! A JavaScript promise handles all errors for you and executes the onError()
callback. The error
object contains very useful information about what went wrong.
做完了! JavaScript承诺会为您处理所有错误,并执行onError()
回调。 error
对象包含有关发生问题的非常有用的信息。
If you look under the hood of the ButterCMS client API you’ll see it uses axios. Axios is a promise based HTTP client that works in the browser and Node.js.
如果您查看ButterCMS客户端API的内幕,您会发现它使用axios 。 Axios是基于诺言的HTTP客户端,可在浏览器和Node.js中使用。
Examining the Axios error object you get back through a promise reveals the following error object:
检查通过诺言获得的Axios错误对象将显示以下错误对象:
{data:Object, status:401, statusText:'Unauthorized', headers:Object, config:Object}
The HTTP status code tells me what the error was.
HTTP状态代码告诉我错误是什么。
The type of errors you get will depend on the API behavior. For example, the ButterCMS API docoumentation lists all possible responses. You can get a 400, 401, or a 404 depending on the request.
您得到的错误类型将取决于API行为。 例如,ButterCMS API文档列出了所有可能的响应 。 您可以根据要求获得400、401或404。
One way to deal with these exceptions is to handle each status in a different way. For example, you could handle errors:
处理这些异常的一种方法是以不同的方式处理每个状态。 例如,您可以处理错误:
butter.post.retrieve('example-post') .catch(function onError(error) { if (error.status === 400) { console.log('Bad request, often due to missing a required parameter.'); } else if (error.status === 401) { console.log('No valid API key provided.'); } else if (error.status === 404) { console.log('The requested resource doesn\'t exist.'); } });
By using the HTTP status as the source of truth, you can interpret the reason for the error however you want.
通过使用HTTP状态作为事实的来源,您可以根据需要解释错误的原因。
Other companies, like the Stripe API client, solve the problem with an error type on the response. The error typestatus
code tells you what type of error is coming back in the response.
其他公司,例如Stripe API客户端 ,通过响应中的错误类型解决了该问题。 错误typestatus
代码告诉您响应中又返回哪种类型的错误。
With all this, one final question remains. “What happens when the network request times out?”
有了这些,最后一个问题仍然存在。 “当网络请求超时时会发生什么?”
For a client API, any request over a network is very risky. Network connectivity can be a luxury one can’t afford at times.
对于客户端API,通过网络进行的任何请求都是非常危险的。 网络连接有时是一种无法承受的奢侈品。
Let’s examine what error exception you get when it times out. The ButterCMS client API has a default value of 3000 ms or 3 seconds.
让我们检查一下超时时得到的错误异常。 ButterCMS客户端API的默认值为3000毫秒或3秒。
Take a look at this error object when it times out from the exception handler:
看一下此错误对象在异常处理程序中超时的情况:
{code:'ECONNABORTED', message:String, stack:String, timeout:3000}
Like any good error object, it has plenty of good details about the exception. Note this error object is different from the one we saw earlier. One distinct difference is the timeout
property. This can be useful in dealing with this kind of exception in a unique way.
像其他任何好的错误对象一样,它具有大量有关异常的详细信息。 请注意,此错误对象与我们之前看到的对象不同。 区别在于timeout
属性。 这对于以独特的方式处理此类异常很有用。
The question is, “Is there a graceful way to handle these kinds of exceptions?”
问题是:“是否有一种优雅的方式来处理这类异常?”
One idea is to auto-retry the request after it fails. Anything that waits for a network response can fail. The failure occurs because of circumstances outside your direct control. As developers, it is nice to be in control but life comes with many exceptions.
一种想法是在请求失败后自动重试。 任何等待网络响应的操作都可能失败。 发生故障是由于您无法直接控制的情况。 作为开发人员,受到控制很高兴,但生活中有许多例外。
Polly-js can attempt to retry the action once it detects an error. The polly-js library can handle exceptions through a JavaScript promise. This promise catches the exception in case all the retries fail and executes the catch()
. But, we decided not to use polly-js because it is an extra dependency that adds bloat to the client API.
一旦检测到错误, Polly-js可以尝试重试该动作。 polly-js库可以通过JavaScript承诺处理异常。 如果所有重试均失败,则该promise捕获异常,并执行catch()
。 但是,我们决定不使用polly-js,因为它是一个额外的依赖项,给客户端API增加了膨胀。
One design principle at play here is: “A little copy-paste is better than an extra dependency.” The bulk of the retry logic is minimal and has exactly what we need to solve the problem.
在这里发挥作用的一个设计原则是:“复制粘贴胜于附加依赖。” 重试逻辑的大部分是最小的,并且正是我们解决问题所需要的。
The crux of auto retries returns a JavaScript promise:
自动重试的关键在于返回JavaScript承诺:
function executeForPromiseWithDelay(config, cb) { return new Promise(function (resolve, reject) { function execute() { var original = cb();
original.then(function (e) { resolve(e); }, function (e) { var delay = config.delays.shift();
if (delay && config.handleFn(e)) { setTimeout(execute, delay); } else { reject(e); } }); }
execute(); });}
The promise has the resolve
and reject
callbacks encapsulated for automatic retries. The config.handleFn()
callback figures out what condition will cause it to retry. The config.delays.shift()
will remove the first item from the list and delay the next attempt.
Promise封装了用于自动重试的resolve
和reject
回调。 config.handleFn()
回调指出什么条件将导致其重试。 config.delays.shift()
将从列表中删除第一项,并延迟下一次尝试。
The good news is it can meet a specific condition before there are any retries. The library has a handle()
function to set the callback that evaluates the condition. You tell it how many retries, give the condition, and final exception handling.
好消息是,在重试之前它可以满足特定条件。 该库具有一个handle()
函数来设置评估条件的回调。 您可以告诉它重试多少次,给出条件以及最终的异常处理。
The ButterCMS client API has retry
capabilities out of the box. To enable auto retries you need this:
ButterCMS客户端API具有开箱即用的retry
功能。 要启用自动重试,您需要这样做:
butter.post.retrieve('example-post') .handle(function onError(error) { // Only retry on time out return error.timeout; }) .executeWithAutoRetry(3) .then(function onSuccess(resp) { console.log(resp.data); }) .catch(function onTimeoutError(error) { if (error.timeout) { console.log('The network request has timed out.'); } });
The executeWithAutoRetry()
staggers subsequent requests and retries if there is a failure. For example, the first attempt will fail then wait 100ms before the second attempt. The second attempt, if it fails, will wait 200ms before the third. The third attempt will wait 400ms before the fourth and final attempt.
executeWithAutoRetry()
交错后续请求,如果失败,则重试。 例如,第一次尝试将失败,然后在第二次尝试之前等待100ms。 如果第二次尝试失败,它将在第三次尝试之前等待200毫秒。 第三次尝试将在第四次也是最后一次尝试之前等待400毫秒。
With the ButterCMS API client, you now have a nice way of handling promise based exceptions. All you need to do is configure it to your liking.
使用ButterCMS API客户端,您现在有了处理基于承诺的异常的好方法。 您需要做的就是根据自己的喜好对其进行配置。
When it comes to errors, you can either bury your head in the sand or handle the unexpected with grace and elegance. Any client API that waits for a response through a connection is prone to exceptions. The choice is yours on what to do when erratic behavior happens.
当涉及到错误时,您既可以将头埋在沙子里,也可以用优雅和优雅来应对意外情况。 任何等待通过连接响应的客户端API都容易出现异常。 选择由您决定何时出现不稳定行为。
Consider an exception as unpredictable behavior. Except, because it is unpredictable does not mean you can’t prepare in advance. When handling exceptions, focus on anticipating what went wrong, not application logic.
将异常视为不可预测的行为。 除外,因为它不可预测并不意味着您无法提前准备。 处理异常时,应着重于预测出了什么问题,而不是应用程序逻辑。
Network connectivity is one of the worst culprits of failures. Be sure to prepare in advance, to give requests a second change in case of a failed connection.
网络连接是故障的最严重原因之一。 如果连接失败,请确保事先做好准备,以便再次更改请求。
This article was originally published on our blog.
本文最初发布在我们的博客上 。
For more content like this, follow ButterCMS on Twitter.
有关更多内容,请在Twitter上关注ButterCMS。
node.js api接口