代码:
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
email: "example@gmail.com",
password: "password",
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow",
};
let data;
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
})
.catch((error) => console.log("error", error));
console.log(data);
我得到的结果是不确定的。我想要的结果是通过async/await将fetch中的结果对象存储在数据中。
在请求完成和数据接收之前,对console.log
的调用正在执行。
执行顺序与编写代码的顺序不同。可能的事件链是:
- 创建名为
data
的未定义变量 - 使用fetch API向
/users/login
发出请求,该请求将异步执行 - 调用
console.log
并引用仍然是undefined
的data
- 请求已完成,因此调用传递给
fetch.then
的回调,并定义data
在使用data
之前,您需要等待请求完成并解析响应。
你可以用几种不同的方法来做到这一点。使用承诺:
let data;
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
// Now that `data` has been defined, we can do something with it
console.log(data);
})
.catch((error) => console.log("error", error));
带异步/等待
// Note the async keyword
async function foobar() {
let data;
// Note the await keyword
await fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
data = JSON.parse(result);
})
.catch((error) => console.log("error", error));
console.log(data);
}
// There are other improvements that could be made to this example also
// to make it more idiomatic. For example:
async function foobar() {
let data;
// Use try/catch instead of `Promise.catch`
try {
const response = await fetch('/users/login', requestOptions);
// Use the `.json` method on the fetch response object
data = await response.json();
} catch (error) {
console.log('error', error);
}
console.log(data);
}
需要注意的重要一点是,在承诺的上下文中发生的任何操作(在您的情况下,分配给data
将异步发生。该操作可能在任何给定时刻完成,也可能没有完成。
现在通常建议使用async/await作为最佳实践。这需要ES6支持,但这通常是在2020年给出的,并且在浏览器和Node中已经支持了多年。
使用async/await可以让您编写异步代码,而不会出现可怕的";回调地狱";承诺,并允许你写更具表现力的&更像过程代码的可读代码。
使用async/await时需要记住的一点是,await
关键字只能在与async
关键字标记为异步的函数中使用,如上例所示。
不能打印其值在异步块中初始化的变量。
如果您将数据更改为那样,它将正确打印数据。
fetch("/users/login", requestOptions)
.then((response) => response.text())
.then((result) => {
const data = JSON.parse(result);
console.log(data);
})
.catch((error) => console.log("error", error));
因此,要对这些数据执行操作,您必须在then块中执行,因为它是这个promise的解析函数。
否则,如果支持async/await
语法,则可以使用它。你可以把它做成那样。
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
email: "example@gmail.com",
password: "password",
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow",
};
try{
const data = await fetch("/users/login", requestOptions);
console.log(data);
catch(err){
console.log('error', err);
}