Fetch API - 使用状态码200返回空响应体的GET请求

5
我遇到了一个非常奇怪的问题。这段 Javascript 代码应该使用 GET 请求从后端获取一个对象。我收到的响应头状态是 200,但响应体似乎为空。

function GetAssignment() {
    assignment = fetch(GetAssignmentURL,
        {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                
            }
        })
        .then((response) => {
            if (response.status == 200) {
                console.log(response);
                return response.json();
            }
            else
            {
                throw `error with status ${response.status}`;
            }
        })
        
        .catch((exception) => {
            console.log(exception);
        }); 
}

响应: https://istack.dev59.com/B3pfo.webp

现在,我用 Postman 试了同样的事情,在那里它运行得很好。(我已经检查了调用后端的URL,并且在Postman和Javascript中完全相同,所以错误并不在那里。) 结果: https://istack.dev59.com/H6Pnm.webp

所以,我想知道我的 Javascript 代码有什么问题。我调试了后端,当我使用 Javascript 调用时,它确实返回了一个像应该一样的对象。我总是用这种方式进行 GET 请求,但现在突然间,响应主体在我的应用程序前端被阻碍了。

有人遇到过同样的问题吗?

1个回答

4

在您所展示的代码中,实际上没有使用body。你在告诉它读取body之前记录了response,而你的assignment变量只是来自fetch的promise,并未尝试对其进行任何操作。

要查看body,您需要查看从json返回的promise的完成值(这将完成两件事:1. 读取body,2. 将其从JSON解析)。

例如:

function GetAssignment() {
    fetch(GetAssignmentURL,                 // *** No `assignment =` on this line
        {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                
            }
        })
        .then((response) => {
            if (response.status == 200) {   // *** This can be just `if (response.ok) {`
                console.log(response);      // *** This is premature
                return response.json();
            }
            else
            {
                throw `error with status ${response.status}`;
            }
        })
        .then(assignment => {               // ***
            // ...use `assignment` here...  // ***
        })                                  // ***
        .catch((exception) => {
            console.log(exception);
        }); 
}

但是:如果目标是将 assignment 传递给调用函数的代码,则需要返回 promise 链,如下所示:

function GetAssignment() {
    return fetch(GetAssignmentURL,
        {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                
            }
        })
        .then((response) => {
            if (response.status == 200) {   // *** This can be just `if (response.ok) {`
                console.log(response);      // *** This is premature
                return response.json();
            }
            else
            {
                throw `error with status ${response.status}`;
            }
        });
}

使用该代码的方式如下:

GetAssignment()
.then(assignment => {
    // ...use `assignment` here...
})
.catch(error => {
    // handle/report error
});

顺便提一下:如果 GetAssignment 没有意图使用 new,那么 JavaScript 中的一个普遍惯例是它应该以小写字母开头:getAssignment


另外,因为 ES2018 已经发布了几年了,对于现代环境的使用(或者如果您正在进行转换),您可以使用 async 函数,这使得您能够编写更不用担心时间问题的逻辑。 async 函数返回 promises,并且让您使用 await 在等待 promise settle 的同时暂停您的逻辑:

async function getAssignment() {
    const response = await fetch(GetAssignmentURL, {
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            
        }
    });
    if (!response.ok) {
        throw `error with status ${response.status}`;
    }
    return response.json();
}

在以上代码中,fetch的调用是同步进行的,但是该函数会挂起自己等待结果并返回一个 promise 对象。它返回的 promise 对象将基于它所 await 的 promise 对象的结果来解决。最终,如果一切顺利,该 promise 对象将被你所 return 的值(或者在上述情况下,当其解决时所提供的response.json()的解决值)来满足。

在另一个async函数中可以这样使用:

const assignment = await getAssignment();
// ...use `assignment` here...

(如果出现错误,上述代码中的async函数将拒绝该Promise)

1
@MathiasGielen - 很高兴能帮到你。只是要注意时间:GetAssignmentfetch操作完成之前就已经返回了。我之所以提到这一点,是因为在你之前删除的评论中,似乎你没有意识到这一点。 :-) 祝编码愉快! - T.J. Crowder
是的,这是另一件事情... 当函数执行到response.json()时,它停止并跳转到我声明assignment并对其属性进行操作的部分。当然,异常提示说我不能对空值进行操作。在此之后,它到达了.then,我的变量接收响应体的值,但那时已经太晚了。我该如何在函数返回之前将响应体分配给我的变量? - Mathias Gielen
1
@MathiasGielen - 你实际上无法这样做,你必须按照上述方式进行操作。更多信息:https://dev59.com/RGYq5IYBdhLWcg3wwDRA async函数提供了(更好的)语法。 - T.J. Crowder
我搞定了。 我几乎把整个代码都粘贴到.then函数里面。 用if函数检查分配是否为空。 如果是,则会跳过所有内容,并继续执行函数之外的代码,避免崩溃。 最终,.then将再次被调用,这次带有一个值,因此代码将被执行。 :-) - Mathias Gielen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接