javascript - 复杂的异步流程未能按预期执行

标签 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 step 8, step 9

  } else {
    console.log('DEBUG::step 7:');
    //Perform other operation
  }
}

基本上,refreshToken()是一个方法,它是解码jwt以检查是否过期,如果过期,则调用REST检索新的 token ,因此上面有一个网络请求,并且函数refreshToken将返回一个 bool 值来指示整个刷新 token 流程是成功还是失败。

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;
  }
};

下面是打印的日志

DEBUG::step 1:

DEBUG::step 2:

DEBUG::step 3:

DEBUG::step 4:

DEBUG::hihi0:

DEBUG::step 7:

DEBUG::hihi1:

  • 为什么Step 7hihi1之前打印?我已经将其设置为async wait

  • 第6步未打印,因此refreshToken操作成功

  • hihi3 未打印,因此也不异常(exception)

任何帮助将不胜感激!

更新!

正如 @CertainPerformance 和 @briosheje 所评论的:我已更新为以下内容:

jobSearch();

const jobSearch = () => {
  return async (dispatch) => { //<==HERE

  console.log('DEBUG::step 1:');

  const shouldRefreshToken = await refreshToken();//<==HERE
  if (!shouldRefreshToken) {//<===HERE
    console.log('DEBUG::step 6:');
    //.......
    //Call function to print step 8, step 9

  } else {
    console.log('DEBUG::step 7:');
    //Perform other operation
  }
}

然后流程变为出现异常,如下所示:

DEBUG::step 1:

DEBUG::step 2:

DEBUG::step 3:

DEBUG::step 4:

DEBUG::hihi0:

DEBUG::step 6:

DEBUG::hihi1:

最佳答案

if (!refreshToken()) {
     ^------ this is async.. Which returns a Promise<boolean>, which is always truthy.

(如此处所述):

const refreshToken = async () // and some other stuff.

因此,由于它被标记为async,因此它将始终返回一个Promise,这始终会导致一个真值。

由于它是异步的,您应该保留 promise 响应并对其进行评估:

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 语句中使用了 Promise,这总是会导致 if 语句跳过。

关于javascript - 复杂的异步流程未能按预期执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52014068/

相关文章:

javascript - Nativescript:如何从图库获取照片列表

javascript - 如何保护 AngularJS $http.post 数据?

javascript - Accordion ,将电子邮件地址复制到每个文本字段

reactjs - 为什么我的 cookie 没有被发送? ReactJS 前端,Go 后端

html - 具有完整性的异步 css

在 Javascript 中使用设置间隔函数在 IE 中无法正确调用 PHP

javascript - 迭代 react 组件

reactjs - 如何定义可能未定义的类型

javascript - 无法理解 async/await Nodejs

java - 如何等到所有一系列嵌套的 CompletableFuture 都完成?