考虑以下Javascript / React代码:
// Javascript function that has a fetch call in it.
export const signIn = (email:string, password:string) => {
console.log("FETCHING...");
fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
.then((response) => {
return response.json()
})
.then(({ data }) => {
console.log("FETCHED DATA...")
})
.catch((error) => {
console.error('ERROR: ', error)
})
console.log("DONE FETCHING...");
}
// A functional component that references signIn.
export const SignIn: React.FC<Props> = () => {
// irrelevant code ...
const onSubmit = (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
signIn(email, password, setAuthentication, setCurrentUser)
console.log("SIGNED IN...");
}
return <>A form here submits and calls onSubmit</>
}
这将产生以下控制台日志输出:
SIGNING IN...
FETCHING...
DONE FETCHING...
SIGNED IN...
FETCHED DATA...
我希望FETCHED DATA...
出现在DONE FETCHING...
之前。我已经尝试过aysnc/await
,但是那没有用,所以我不知道从这里去哪里。
答案 0 :(得分:3)
只需添加另一个.then
#include <iostream>
#include <limits>
#include <cstdlib>
class seconds
{
protected:
int secs;
public:
seconds()
{
secs = 0;
}
void getsecs()
{
std::cout << "\n enter the time in seconds:";
std::cin >> secs;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
};
class minutes : public seconds
{
protected:
int mins;
public:
minutes()
{
mins = 0;
}
void convert()
{
getsecs();
mins = secs / 60;
secs %= 60;
}
};
class hours : public minutes
{
protected:
int hrs;
public:
hours()
{
hrs = 0;
}
void convert1()
{
convert();
hrs = mins / 60;
mins %= 60;
}
void show()
{
std::cout << "hrs:" << hrs << "\t mins" << mins << "\t secs" << secs;
}
};
int main()
{
std::system("clr");
hours h;
h.convert1();
h.show();
std::cin.get();
return 0;
}
答案 1 :(得分:3)
如果您想让then
等到承诺被兑现,则必须在console.log
语句中。这是一个使用async/await
的示例:
export const signIn = async (email:string, password:string) => {
console.log("FETCHING...");
const response = await fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
const data = await response.json();
console.log("FETCHED DATA...")
console.log("DONE FETCHING...");
}
如果您希望console.log在完成数据提取之后发生,您还需要将其转换为async
函数:
const onSubmit = async (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
await signIn(email, password, setAuthentication, setCurrentUser)
console.log("SIGNED IN...");
}
答案 2 :(得分:3)
为了使用异步等待,您需要从调用中返回一个承诺。因此,基本上,您无需执行.then
并将调用包装在try catch块中。
export const signIn = async (email:string, password:string) => {
console.log("FETCHING...");
return fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
}
和
const onSubmit = async (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
try {
const data = await signIn(email, password, setAuthentication, setCurrentUser)
// Parse data, do something with it.
console.log("SIGNED IN...");
} catch (e) {
// handle exception
}
}
答案 3 :(得分:2)
您可能想更多地了解JavaScript中的promise如何工作。
这里的一个问题是signIn
。您现在正在做的是:
function signIn() {
// 1. log FETCHING
// 2. call asynchronous fetch function
// 3. log DONE FETCHING
}
此处的关键是fetch
是异步。该程序不会等待它完成才继续前进。看到问题了吗? JavaScript解释器将运行第3步,而无需等待第2步完成。
有多种方法可以解决此问题。首先,您可以使用then
。这是一个示例:
promise
.then(res => func1(res))
.then(res => func2(res))
.then(res => func3(res))
在这里,您要告诉JavaScript:
promise
,然后等待它解决 。promise
获取结果并将其传递到func1
。等待func1
解决。func1
获取结果并将其传递到func2
。等待func2
解决。此处的主要区别在于,您正在按顺序运行每个then
块,等待每个先前的承诺得到解决,然后再转到下一个。 (而在您不等待诺言解决之前)。
带有承诺的代码如下:
export const signIn = (email: string, password: string) => {
console.log("FETCHING...")
// Note that we return the promise here. You will need this to get onSubmit working.
return fetch(/* args */)
.then(res => res.json())
.then(({ data }) => console.log("DONE FETCHING"))
.catch(err => /* HANDLE ERROR */)
}
解决此问题的第二种方法是使用async
和await
。 async
和await
只是对诺言的语法糖。它的基本功能是完全相同的,因此请确保您首先了解承诺的工作方式。这是带有async
和await
的代码:
// The async keyword here is important (you need it for await)
export const signIn = async (email: string, password: string) => {
console.log("FETCHING...");
try {
const res = await fetch(/* args */) // WAIT for fetch to finish
const { data } = res.json()
console.log("FETCHED DATA...")
} catch (err) {
/* HANDLE ERROR */
}
console.log("DONE FETCHING...")
}
onSubmit
中还有另一个类似的问题。想法是一样的。我会让你自己弄清楚(重要的是必须从Promise
返回signIn
)。