Javascript 未能按预期执行的复杂异步流
我已经试了好几个小时了,但还是没有得到正确的流程。我将先分享代码,稍后再解释Javascript 未能按预期执行的复杂异步流,javascript,reactjs,asynchronous,promise,async-await,Javascript,Reactjs,Asynchronous,Promise,Async Await,我已经试了好几个小时了,但还是没有得到正确的流程。我将先分享代码,稍后再解释 jobSearch(); const jobSearch = () => { return (dispatch) => { console.log('DEBUG::step 1:'); if (!refreshToken()) { console.log('DEBUG::step 6:'); //....... //Call function to print
jobSearch();
const jobSearch = () => {
return (dispatch) => {
console.log('DEBUG::step 1:');
if (!refreshToken()) {
console.log('DEBUG::step 6:');
//.......
//Call function to print step 8, step 9
} else {
console.log('DEBUG::step 7:');
//Perform other operation
}
}
基本上,refreshToken是一种对jwt进行解码以检查到期的方法,如果到期,则调用REST以检索新的令牌,因此上面有一个网络请求,函数refreshToken将返回一个布尔值以指示整个刷新令牌流是成功还是失败
const refreshToken = async () => {
console.log('DEBUG::step 2:');
let valid = true;
if (!validateAccessToken()) { //<==just a flow to decode jwt, no async flow
console.log('DEBUG::step 4:');
// Configure retry operation
const operation = retry.operation({
retries: MAX_RETRIES_USER_LOGIN,
factor: 1,
minTimeout: INTERVAL_RETRY_USER_LOGIN,
maxTimeout: INTERVAL_RETRY_USER_LOGIN
});
// Configure HTTP request
const ax = axios.create({
timeout: TIMEOUT_CONNECT,
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
cancelToken: cancelTokenSourceJobSearch.token
});
console.log('DEBUG::hihi0:');
await operation.attempt(() => {
ax.post(urljoin(API_BASE_URL, API_ENDPOINT_TOKEN_REFRESH), {
data: {
refresh_token: global.setting.refresh_token
}
})
.then(({ data }) => {
valid = true;
console.log('DEBUG::hihi1:');
//SUCCESS!
}).catch((err) => {
console.log('DEBUG::hihi3:');
// Log error to console
console.log(err);
if (axios.isCancel(err)) {
valid = false;
return;
} else if (operation.retry(err)) {
valid = false;
return;
}
});
return valid;
});
} else {
console.log('DEBUG::step 5:');
return valid;
}
};
然后流更改为getting exception,如下所示:
调试::步骤1:
调试::步骤2:
调试::步骤3:
调试::步骤4:
调试::HI0:
调试::步骤6:
调试::hihi1:
因此,由于它被标记为async,它将始终返回一个承诺,这总是导致一个真实的值
因为它是异步的,所以您应该遵守承诺响应并对其进行评估:
console.log('DEBUG::step 1:');
// Store here the value of refreshToken
const shouldRefreshToken = await refreshToken();
if (!shouldRefreshToken) {
// ^--- Syncronous flow here.
console.log('DEBUG::step 6:');
//.......
} else {
console.log('DEBUG::step 7:');
//Perform other operation
}
除此之外,refreshToken方法内部的顺序取决于您在其中使用的方法。如果出于某种原因,您需要console.log'DEBUG::hihi3:';要调用,请查看axios文档或其他任何内容。
在任何情况下,主要的问题是您在if语句中使用了一个承诺,这总是会导致if语句跳过。refreshToken是异步的,因此您在一开始就忘记了等待refreshToken。或者调用。然后在它上检查其值。refreshToken,返回一个承诺,将始终truthy@CertainPerformance当前位置我刚刚根据您所说的内容进行了更新,但现在日志的打印方式有所不同。从步骤1到hihi0,但不是步骤7,而是打印步骤6,hihi1@Isaac第8步和第9步在哪里?@briosheje,很抱歉遗漏了这一点,因为这并不重要,我已经从我的评论中删除了。并增加了问题,如果无论如何相关,但我怀疑索克斯。。。有一个自己的流,它不是主流的一部分。在操作前粘贴等待。尝试无效。你可以尝试返回斧头。后。。。但这项操作的成功与否取决于.trunt返回的操作,我不知道。我已更新了我的问题并尝试了您的解决方案,但在tooconsole.log'DEBUG::hihi3:'中失败;只有在网络请求失败时才会打印,所以我没有预料到。放在那里只是为了表明我们的请求没有失败
if (!refreshToken()) {
^------ this is async.. Which returns a Promise<boolean>, which is always truthy.
const refreshToken = async () // and some other stuff.
console.log('DEBUG::step 1:');
// Store here the value of refreshToken
const shouldRefreshToken = await refreshToken();
if (!shouldRefreshToken) {
// ^--- Syncronous flow here.
console.log('DEBUG::step 6:');
//.......
} else {
console.log('DEBUG::step 7:');
//Perform other operation
}