背景
我煮了一个非常基本的(< script>
tag!inline js!)Web应用程序,它使我也实现了API的REST API请求。
我是WebDev的新手,并认为我应该检查 Response.Status
,但在这样做时,我注意到许多其他海报都有的事情: fetch()
>函数返回一个包含状态>和标题
属性的对象,带有空 body
或,如果是响应主体 .json()()
函数在 response.json()()
我的问题上调用
:我想使用 response.status 在A 中,在异步函数之外的单独的逻辑/函数中,我将fetch in 包裹在中,以操作是否在某些内联HTML或预期的预期结果中显示错误消息。但是,正如您可能想象的那样,响应
对象仅在调用 .json()
的情况下包含正文,如果不是,则只能调用一个空/怪异的Promise-Y对象。
对 fetch()
的设计使我的用例是否为 wendesp.Status
被视为“最佳实践”,或者是“行业方法”,只是仅评估该方法响应主体,如果响应主体除了预期的模式以外的其他东西,那么将其作为错误处理?
相关的次要问题
在尝试了解有关获取和异步函数行为的更多信息时,我读到,用 then()。不规则(甚至是一种反模式?) - 如果MDN自己的异步文档在自己的教程中使用此语法,为什么会这样?
关联:
更多的背景故事
在拖网数十个stackoverflow帖子之后javascript-fetch-api-why-does-response-json-return-a-promise-object-instead“>这个,我意识到我可以可以组合响应。 json()
对象和 wenders.status
kvp to以此代码为新对象:
// we have to await the .json() which is a function that returns a promise
const respObj = await response.json();
//now, create and return a 'resp' object that has all desired response elements:
const resp = {
"status":response.status,
"body":respObj
};
return resp;
Background
I cooked up a very basic (inline js in the <script>
tag!) web app that makes a rest API request of an API I also implemented.
I'm a novice to webdev and figured that I should inspect the response.status
but in doing so I noticed the same thing numerous other posters have: that the fetch()
function returns either an object that contains status
and Header
properties with an empty body
or just the response body if the .json()
function was invoked on response.json()
My question: I wanted to use the response.status
in a separate piece of logic/function outside of the async function I wrapped fetch in to action on whether or not to display an error message in some inline HTML or the parsed expected outcome. However, as you probably figured, the response
object only contains the body if .json()
was called, and an empty/weird Promise-y object if not.
This design to fetch()
made wonder if my use-case for response.status
was considered a "best practice" or is the "industry approach" to simply just evaluate the response body, and if the response body is anything other than the expected schema, then handle that as an error?
Related secondary question
In trying to learn more about the fetch and async function behavior, I read that chaining an invoked async function with a .then().catch()
expression is irregular (maybe even an anti pattern?) - why would this be the case if MDN's own async docs use this syntax in their own tutorials?
link:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options
More backstory
After trawling dozens of stackoverflow posts like this one, I realized I could combine the response.json()
object and the response.status
kvp into a new object with this code:
// we have to await the .json() which is a function that returns a promise
const respObj = await response.json();
//now, create and return a 'resp' object that has all desired response elements:
const resp = {
"status":response.status,
"body":respObj
};
return resp;
发布评论
评论(1)
如果您还要访问响应的元素,除了仅分析的JSON之外,请务必创建自己的函数,该函数调用
fetch()
并使用一些逻辑,然后返回响应的多个部分数据。我个人可能不会重新包装响应
数据结构,而只是保持完整,以便呼叫者可以从那里得到任何东西,包括标题等...这是一个示例:
此功能返回承诺该解决方案既包含解析的JSON数据和原始响应对象)的对象。这使呼叫者可以在原始响应对象中检查他们想要的任何内容。
如果
wenders.ok
不正确,则它将用包含原始响应对象的错误对象拒绝。这并不是真正思考它的正确方法。
fetch()
和response.json()
返回承诺。fetch()
返回的承诺将解析为响应
对象。response.json()
返回的承诺将解析为解析的JSON数据对象。如果您使用等待
,则可以使用承诺直接获得解决结果(如上所述,如上所述)。通常检查
respons.ok
,因为4xx或5xx状态不会拒绝fetch()
的承诺。如果您专门寻找3XX错误,则可以编写特定代码以检查。Response.ok
会告诉您它是否是2xx状态(通常在请求数据时您想要的内容)。您可以跳过此检查并在尝试阅读/解析JSON时“假设”下游,如果没有JSON,您将获得错误(情况是这样,但这可能是JSON解析错误,而不是一个指出真正的问题是,这不是返回所需数据的2xx状态。 从我的角度来看)。请求被认为是成功的( 该过程。或包含无效的JSON,它将拒绝,您的代码可以检查结果错误对象,以查看其拒绝的原因。
因此,您通常不想将很多
async/等待
和.then()
和.catch()
在同一函数中由于控制流程可能会造成混乱。如果将函数标记async
,则可能在其中使用等待
而不是。代码> async
函数是通过使用等待
来启用更简单的控制流。在某些情况下,我会发现.catch()
是更简单,更少的代码要在当地处理错误,但这对我来说不是很常见的情况。我不会那么远地称其为反模式来偶尔找到
a
.catch()
比try/catch
等待的情况更简单
,但这实际上只是个人喜好。但是,我将其称为一个反模式,可以自由地混合等待
和.then()
,async
函数。这只是使代码更加复杂。通常,您想在给定功能中为代码选择一种或另一种样式。If you want access to elements of the response besides just the parsed JSON, then by all means, you can create your own function that calls
fetch()
and uses some logic and then returns multiple pieces of the response data. I would personally probably not repackage theresponse
data structure, but rather just leave it intact so the caller can get anything they want from there including headers, etc...Here's an example:
This function returns a promise that resolves to an object that contains both the parsed JSON data and the original response object. This allows the caller to check on anything they want to in the original response object.
If
response.ok
is not true, then it will reject with an error object that also contains the original response object.That's not really the right way to think of it. Both
fetch()
andresponse.json()
return promises. The promise thatfetch()
returns will resolve to theresponse
object. The promise thatresponse.json()
returns will resolve to the parsed JSON data object. If you useawait
with each of these, then you can use the promise to just directly get the resolved result (as shown in my example above).It is common to check
response.ok
because a 4xx or 5xx status does not reject the promise fromfetch()
. If you're specifically looking for a 3xx error, then you may write specific code to check for that.response.ok
will tell you if it is a 2xx status (usually what you want when requesting data). You can skip this check and "assume" that downstream when you try to read/parse the JSON, you will get an error if there was no JSON (and this is the case, but it will likely be a JSON parse error, not an indication of the real problem that it wasn't a 2xx status that returned the desired data. So I find it better to specifically checkresponse.ok
so I know I'm only trying to parse JSON if the request was deemed successful (from my point of view).You will find that third party browser libraries that offer a bit more convenient interface such as
axios()
don't even make you handle two separate steps in the process. You just make a request and they return data or an error. That's what my smallfetchJSON()
function above does too. It handles the internal checks itself. If the response doesn't contain JSON or contains invalid JSON, it will reject and your code can check the resulting error object to see why it rejected.So, you generally don't want to mix lots of
async/await
and.then()
and.catch()
within the same function as the flow of control can get confusing to follow. If you mark the functionasync
, then inside it you're probably usingawait
instead of.then()
because the whole point of anasync
function is to enable the simpler flow of control by usingawait
. There are occasional cases where I find a.catch()
to be simpler and less code that atry/catch
around anawait
when I want to handle the error locally, but that's not a very common case for me.I wouldn't go so far to call it an anti-pattern to occasionally find a situation where
.catch()
is simpler thantry/catch
around anawait
, but that's really just personal preference. But, I would call it an anti-pattern to be freely mixingawait
and.then()
all over anasync
function. That just makes the code more complicated to follow. In general, you want to pick one style or the other for your code within a given function.