vue-router - Uncaught(in promise)错误:通过导航防护从“/login”重定向到“/”

xwmevbvl  于 2023-03-31  发布在  Vue.js
关注(0)|答案(9)|浏览(1846)

为什么vue-router给我这个错误?要清楚的是,登录流程按预期工作,但我想a)摆脱错误和b)理解为什么会发生错误。

错误:

未捕获(承诺中)错误:通过导航保护从“/login”重定向到“/”。

登录流程

1.开始注销,但输入需要auth的URL(即除了“/login”之外的任何内容)
1.得到重定向到“/login”(如预期)。
1.登录
1.成功地从步骤#1重定向到起始URL,除了上面的错误。

登录操作:

doLogin({ commit }, loginData) {
  commit("loginStart");
  axiosClient
    .post("/jwt-auth/v1/token", {
      username: loginData.username,
      password: loginData.password,
    })
    .then((response) => {
      commit("loginStop", null);
      commit("setUserData", response.data);
      this.categories = airtableQuery.getTable("Categories");
      commit("setCategories", this.categories);
      this.locations = airtableQuery.getTable("Locations");
      commit("setLocations", this.locations);
      router.push("/"); // push to site root after authentication
    })
    .catch((error) => {
      console.log(error.response.data.message);
      commit("loginStop", error.response.data.message);
      commit("delUserData");
    });
},

路由器:

const routes = [
  {
    path: "/login",
    name: "Login",
    component: Login,
    meta: { requiresAuth: false },
  },
  {
    path: "/",
    name: "Home",
    component: Home,
    meta: { requiresAuth: true },
  },
];

let entryUrl = null;
router.beforeEach((to, from, next) => {
  let localStorageUserData = JSON.parse(localStorage.getItem("userData"));
  let storeUserData = state.getters.getUserData;
  let userData = localStorageUserData || storeUserData;
  let isAuthenticated = userData.token !== "" && userData.token !== undefined;
  if (to.matched.some((record) => record.meta.requiresAuth)) {
    if (!isAuthenticated) {
      if (to.name !== "Login" && to.name !== "Home") {
        entryUrl = to.fullPath;
      }
      next({ name: "Login" });
    } else if (entryUrl) {
      let url = entryUrl;
      entryUrl = null;
      next(url);
    } else {
      next();
    }
  } else {
    next();
  }
});
lvmkulzt

lvmkulzt1#

我花了几个小时对此进行调试,并得到了以下丑陋的Uncaught (in promise) Error: Redirected when going from ...错误的结果。
请注意,该错误不是针对“重定向”。它是针对第一个导航的初始调用者。继续阅读...
这是设计好的,为什么?
阅读这篇评论。
TL;DR:假设你在A页,点击一个按钮可以转到B页(有点像A页上的method: goToB() { router.push('/B'); }),但是B页有一个Navigation Guard,它会把你转到C页。
此错误是让goToB()函数知道路由器无法完成所需任务的一种方式,并且用户尚未登陆/B

这很恶心,但信息量很大

这里最大的困惑是重定向(登陆页面C)是,两者都是:

  • 一个“预期”的结果给你,系统的架构师。但是,同时,
  • 页面A中goToB的调用方(即router.push)发生**“意外”**事件,该调用方希望路由器转到页面B。

这就是为什么当它弹出为Error时,它会让**“你”**感到困惑和沮丧,因为你会完全查看系统,并认为没有任何错误或错误!
呃...那我该怎么办?

我遇到过一个情况,<router-link>工作正常,但router.push却在抱怨(我认为router-link在内部抑制了这样的错误)。

方案2.1:每个router.push调用上的单个抑制错误

router.push函数返回一个Promise(因为它可以被认为是或将被认为是一个异步作业)。

router.push('/B').catch(() => {});
//     Add this: ^^^^^^^^^^^^^^^^

方案2.2:增强Router.prototype.push以始终抑制错误

如果你认为你有多个这样的示例,你可以通过同一条评论上的片段在Routerprototype上增加push函数,将其应用于整个应用程序上的所有router.push调用。
好消息是,它提供了粒度级别来选择要抑制的错误(例如,仅NavigationFailureTypes.redirected错误。
如果你使用的是TypeScript,请在转换和输入https://gist.github.com/eyedean/ce6ab6a5108a1bd19ace64382144b5b0时成为我的客人:)

其他提示:

1.升级你的vue-router!当你读到这篇文章的时候,你的案子可能已经解决了。(因为他们显然有这样做的计划。)
1.如果您有多个导航卫士,请确保您没有分叉或到达死胡同。一个接一个地跟踪它们并一步一步地跟踪它们。请注意,双重重定向是可以的(感谢this answer),您只需要加倍小心!
1.我这里还有一个Playground:https://codepen.io/eyedean/pen/MWjmKjV您可以根据自己的需要开始模仿这一点,以找出问题首先发生在哪里。

ioekq8ef

ioekq8ef2#

错误消息将在下一个版本的vue-router中更新。错误将显示:
通过导航防护从“/login”转到“/”时重定向
在你的代码中,在被重定向到“/login”之后,你又重定向回了“/”。vue-router正在抱怨。你需要确保每个导航操作只有一个重定向。

yhqotfr8

yhqotfr83#

我也遇到过类似的错误,但是对于**.beforeEach中的onboarding重定向,通过替换.beforeEach**条件逻辑解决了这个问题:

next({ name: "Onboarding" });

router.push({ path: 'Onboarding' });
v6ylcynt

v6ylcynt4#

这个错误是为了通知$router.push的调用者导航没有转到它最初想要的地方。如果你期望重定向,你可以安全地忽略这个错误,使用下面的代码。

import VueRouter from 'vue-router'
const { isNavigationFailure, NavigationFailureType } = VueRouter

...

this.$router.push('/')
  .catch((e) => {
    if (!isNavigationFailure(e, NavigationFailureType.redirected)) {
        Promise.reject(e)
    }
  }

有关此问题的讨论,请参见https://github.com/vuejs/vue-router/issues/2932

7fyelxc5

7fyelxc55#

如果您的重定向是在调用router.push('/someroute)之后,那么您可以捕获此错误,因为router.push()是一个promise,您可以像下面这样附加一个catch

$router.push('/somesecureroute')
.catch(error => {
   console.info(error.message)
})
jbose2ul

jbose2ul6#

我有同样的错误.这个错误由router.push("/");行创建-它试图告诉你,推到主页被重定向在导航后卫中断.但实际上,这不是一个错误,因为它是一个预期的行为.
我通过以下方式忽略了这些错误:

const router = new VueRouter({
    mode: 'history',
    routes: _routes,
});

/**
 * Do not throw an exception if push is rejected by redirection from navigation guard
 */
const originalPush = router.push;
router.push = function push(location, onResolve, onReject) {
    if (onResolve || onReject) {
        return originalPush.call(this, location, onResolve, onReject);
    }
    return originalPush.call(this, location).catch((err) => {
        let reg = new RegExp('^Redirected when going from "[a-z_.\\/]+" to "[a-z_.\\/]+" via a navigation guard.$');
        if (reg.test(err.message)) {
            // If pushing interrupted because of redirection from navigation guard - ignore it.
            return Promise.resolve(false);
        }
        // Otherwise throw error
        return Promise.reject(err);
    });
};
8fsztsew

8fsztsew7#

我有同样的问题,我以为这是配置问题,但它不是你可以试试这个代码

async doLogin({ commit, dispatch }, loginData) {
  commit("loginStart");
  let response = await axiosClient
  .post("/jwt-auth/v1/token", {
    username: loginData.username,
    password: loginData.password,
  })
  return dispacth('attempt', response) 
}

async attempt({ commit }, response) {
  try {
    commit("loginStop", null);
    commit("setUserData", response.data);
    this.categories = airtableQuery.getTable("Categories");
    commit("setCategories", this.categories);
    this.locations = airtableQuery.getTable("Locations");
    commit("setLocations", this.locations);
  }
  catch( (error) => {
    console.log(error.response.data.message);
    commit("loginStop", error.response.data.message);
    commit("delUserData");
  })
}

在调用doLogin操作的组件中

this.doLogin(this.loginData)
    .then( () => {
        this.$router.replace('/')
        .catch( error => {
            console.log(error)
        })
    })
    .catch( e => {
        console.log(e)
    })
8qgya5xd

8qgya5xd8#

我在应用程序 Boot 时发生了这种情况,在授权检查期间,我试图推到'/auth',但该导航被另一个对'/'的调用取消,这发生在我之后。
所以最后我发现可以使用以下命令监听vue-router的就绪状态(https://router.vuejs.org/api/#isready):

await router.isReady()

router.isReady().then(...)
k97glaaz

k97glaaz9#

我有完全相同的问题触发了两个特定的网页,为这两个网页被重定向,由于登录:

if (isAdmin){
   router.push({name: 'page'}).catch(error=>{
          console.info(error.message)}) 
else...

否则,其他普通用户会被推到一个不同的页面,使用“router.push”
仅在抛出原始错误/警告的重定向上。按照前面的评论中的建议取消警告:

if (!to.matched.length) console.warn('no match');
  next()

允许用户在没有适当权限的情况下登录和访问页面。
捕捉错误似乎是要走的路,根据以下建议:基苏

相关问题