在Vanilla HTML/CSS/JS应用程序中检查提取响应对象是否有最佳实践(“正确的方式”)?

发布于 2025-02-11 11:10:32 字数 1696 浏览 0 评论 0 原文

背景

我煮了一个非常基本的(< 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

‘画卷フ 2025-02-18 11:10:32

如果您还要访问响应的元素,除了仅分析的JSON之外,请务必创建自己的函数,该函数调用 fetch()并使用一些逻辑,然后返回响应的多个部分数据。我个人可能不会重新包装响应数据结构,而只是保持完整,以便呼叫者可以从那里得到任何东西,包括标题等...

这是一个示例:

async function fetchJSON(...args) {
    const response = await fetch(...args);
    // check for non 2xx status
    if (!response.ok) {
         throw new Error(`Response status ${response.status}`, { cause: response });
    }
    const data = await response.json();
    return { data, response };
}

此功能返回承诺该解决方案既包含解析的JSON数据和原始响应对象)的对象。这使呼叫者可以在原始响应对象中检查他们想要的任何内容。

如果 wenders.ok 不正确,则它将用包含原始响应对象的错误对象拒绝。

我的问题:我想在单独的逻辑/函数中使用响应。在异步函数之外,我包装了我将是否在某些内联html中显示错误消息或预期的预期的错误消息,以采取行动结果。但是,正如您可能想象的那样,响应对象仅在调用.json()和一个空/怪异的Promise-y对象时包含正文。

这并不是真正思考它的正确方法。 fetch() response.json()返回承诺。 fetch()返回的承诺将解析为响应对象。 response.json()返回的承诺将解析为解析的JSON数据对象。如果您使用等待,则可以使用承诺直接获得解决结果(如上所述,如上所述)。

这种对fetch()设计的设计使我想知道我的响应用例是否被认为是“最佳实践”,还是仅评估响应主体的“行业方法”,以及响应主体是否是其他任何东西比预期的模式,然后将其作为错误处理?

通常检查 respons.ok ,因为4xx或5xx状态不会拒绝 fetch()的承诺。如果您专门寻找3XX错误,则可以编写特定代码以检查。 Response.ok 会告诉您它是否是2xx状态(通常在请求数据时您想要的内容)。您可以跳过此检查并在尝试阅读/解析JSON时“假设”下游,如果没有JSON,您将获得错误(情况是这样,但这可能是JSON解析错误,而不是一个指出真正的问题是,这不是返回所需数据的2xx状态。 从我的角度来看)。

请求被认为是成功的( 该过程。或包含无效的JSON,它将拒绝,您的代码可以检查结果错误对象,以查看其拒绝的原因。

在尝试了解有关获取和异步功能行为的更多信息时,我读到,用.catch()表达式链接一个被调用的异步函数。如果MDN自己的异步文档在自己的教程中使用此语法?

因此,您通常不想将很多 async/等待 .then() .catch()在同一函数中由于控制流程可能会造成混乱。如果将函数标记 async ,则可能在其中使用等待而不是。代码> async 函数是通过使用等待来启用更简单的控制流。在某些情况下,我会发现 .catch()是更简单,更少的代码要在当地处理错误,但这对我来说不是很常见的情况。

我不会那么远地称其为反模式来偶尔找到 .catch() try/catch 等待的情况更简单,但这实际上只是个人喜好。但是,我将其称为一个反模式,可以自由地混合等待 .then() a 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 the response 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:

async function fetchJSON(...args) {
    const response = await fetch(...args);
    // check for non 2xx status
    if (!response.ok) {
         throw new Error(`Response status ${response.status}`, { cause: response });
    }
    const data = await response.json();
    return { data, response };
}

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.

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.

That's not really the right way to think of it. Both fetch() and response.json() return promises. The promise that fetch() returns will resolve to the response object. The promise that response.json() returns will resolve to the parsed JSON data object. If you use await with each of these, then you can use the promise to just directly get the resolved result (as shown in my example above).

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?

It is common to check response.ok because a 4xx or 5xx status does not reject the promise from fetch(). 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 check response.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 small fetchJSON() 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.

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?

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 function async, then inside it you're probably using await instead of .then() because the whole point of an async function is to enable the simpler flow of control by using await. There are occasional cases where I find a .catch() to be simpler and less code that a try/catch around an await 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 than try/catch around an await, but that's really just personal preference. But, I would call it an anti-pattern to be freely mixing await and .then() all over an async 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文