代码之家  ›  专栏  ›  技术社区  ›  Isaac

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

  •  0
  • Isaac  · 技术社区  · 6 年前

    我已经试了好几个小时了,但还是没有得到正确的流量。我先分享代码,然后再解释。

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

    下面是打印的日志

    调试::步骤1:

    调试::步骤2:

    调试::步骤3:

    调试::步骤4:

    调试::hihi0:

    调试::步骤7:

    调试::hihi1:

    • 怎么会 Step 7 以前打印 hihi1 是吗?我已经成功了 async await 是的。

    • step 6 未打印,因此RefreshToken操作成功

    • hihi3 没有打印,所以也不例外

    任何帮助都将不胜感激!

    更新!

    正如@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
      }
    }
    

    然后流更改为获取异常,如下所示:

    调试::步骤1:

    调试::步骤2:

    调试::步骤3:

    调试::步骤4:

    调试::hihi0:

    调试::步骤6:

    调试::hihi1:

    1 回复  |  直到 6 年前
        1
  •  1
  •   briosheje    6 年前
    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语句中,这将始终导致if语句跳过。