Uncaught (in promise) undefined - Vue-router

Posted

技术标签:

【中文标题】Uncaught (in promise) undefined - Vue-router【英文标题】: 【发布时间】:2019-12-20 22:35:39 【问题描述】:

我遇到了一个非常奇怪的问题,如果权限受限的用户尝试登录我的网络应用程序,他们会看到以下错误:

Uncaught (in promise) undefined

但这不会发生在拥有最大权限的用户身上。

我认为问题是由重新路由引起的。如果用户没有 page_access 1,它会路由到 /holidays。另一个奇怪的是,这个错误只会出现一次,那是用户第一次登录的时候。如果页面被刷新或者用户导航到其他页面,它就不会出现。

router.js

Vue.use(Router)

const router = new Router(

  routes: [
    
      path: '/',
      name: 'dashboard',
      component: Dashboard,
      beforeEnter(to, from, next) 
        if(localStorage.token) 
          if(localStorage.page_access.indexOf('1') != -1 && localStorage.page_access != null) 
            next('/holidays');
          
          else 
            next();
          
         else 
          next('/login');
        
      
    ,
    
      path: '/holidays',
      name: 'holidays',
      component: Holidays,
      beforeEnter(to, from, next) 
        if(localStorage.token) 
          next();
         else 
          next('/login');
        
      
    ,
  ],
  mode: 'history'
)

router.beforeResolve((to, from, next) => 

  if(localStorage.token && from.name != 'login' && to.name != 'login') 
    store.dispatch('autoLogin')
    .then(response => 
      store.dispatch('getNavigation');
      next();
    )
    .catch(err => 
      console.log(err);
    );
  
  else if(from.name && !localStorage.token) 
    router.go('/login');
  
  else 
    next();
  
);

export default router;

store.js

async autoLogin(commit) 
    const token = localStorage.getItem('token');
    const remember_token = localStorage.getItem('remember_token');

    if(!token) 
      return;
    

    try 
      const res = await axios(
      method: 'post',
      data:  userId: localStorage.user_id, token: localStorage.remember_token ,
      url: 'https://controlapi.totalprocessing.com/api/get-user',
      config:  headers:  'Content-Type': 'application/x-www-form-urlencoded' 
      )
      .then(response => 
        if(response.data.remember_token == remember_token) 
          commit('authUser',  token: token );
          return response;
        
        else 
          localStorage.clear();
          return null;
        
      )
      .catch(e => 
          this.errors.push(e);
          return e;
      )
      return res;
    
    catch(e) 
      console.log(e);
      return e;
    

getNavigation(commit) 
    let pageAccess = localStorage.page_access == 'null' ? null : localStorage.page_access;
    let subPageAccess = localStorage.sub_page_access == 'null' ? null : localStorage.sub_page_access;

    axios(
    method: 'post',
    data:  pageAccess: pageAccess, subPageAccess: subPageAccess ,
    url: 'https://controlapi.totalprocessing.com/api/client-get-navigation',
    config:  headers:  'Content-Type': 'application/x-www-form-urlencoded' 
    )
    .then(response => 
    console.log(response.data);
        const data = response.data;
        const tree = [];

        data.reduce(function(a, b, i, r) 

            // Add the parent nodes
            if(a.page_id != b.page_id)
                tree.push( page_id: a.page_id,
                            page_name: a.page_name,
                            page_path: a.path,
                            page_icon: a.page_icon
                            );
            

            // Add the last parent node
            if(i+1 == data.length) 
                tree.push( page_id: b.page_id,
                            page_name: b.page_name,
                            page_path: b.path,
                            page_icon: b.page_icon
                            );

                // Add the child nodes to the parent nodes
                data.reduce(function(a, b) 
                    if(a.sub_page_id) 
                        const find = tree.findIndex(f => f.page_id == a.parent_id);

                        // Add the first child node to parent
                        if(!("children" in tree[find])) 
                            tree[find].children = [];

                            tree[find].children.push( page_id: a.sub_page_id,
                                                    page_name: a.sub_page_name,
                                                    page_path: a.sub_page_path,
                                                    page_icon: a.sub_page_icon
                            );
                        
                        // Add the remaining child nodes to parent nodes
                        else 
                            tree[find].children.push( page_id: a.sub_page_id,
                                                    page_name: a.sub_page_name,
                                                    page_path: a.sub_page_path,
                                                    page_icon: a.sub_page_icon
                            );
                        
                    
                    return b;
                );
            
            return b;
        );

        commit('authNav', 
        navigation: tree
        );
    )
    .catch(e => 
        this.errors.push(e)
    )

【问题讨论】:

你能加入getNavigation行动 @Dadboz - 我已经完成了那个伙伴。我不认为这是因为当我注释掉该行时,错误仍然存​​在。 我有同样的问题,但似乎没有什么问题:/ 这里相同...我使用了 enso 的答案,甚至调试了“错误”,它只显示“未定义”。所以有一个错误,但它是未定义的?对我来说似乎是一个错误,即使是 3.1.2 【参考方案1】:

我们的问题是一样的。登录页面可以跳转到这个路径,写:

this.$router.push( path: this.redirect || '/' , onComplete =>  , onAbort =>  )

错误的写法是:

 this. $router. Push (path: this. Redirect | '/')

【讨论】:

【参考方案2】:

根据我过去几天的经验,在调用this.$router.push() 的函数中捕获错误至关重要。

我发现有两种方法非常可行:

handleSomething() 
    this.$router.push().catch((err) => 
        throw new Error(`Problem handling something: $err.`);
    );
,

async handleSomething() 
    try 
        await this.$router.push();
     catch (err) 
        throw new Error(`Problem handling something: $err.`);    
    
,

目前,我更喜欢这里的 async/await 技术,因为它具有执行阻塞的性质,但是您应该注意的关键是“未捕获的 promise”错误本身是 javascript 中经常提到的一个已知问题作为“被吞下的承诺”,它是由被拒绝的 Promise 引起的,但“错误”被吞下,因为它没有被正确捕获。也就是说,没有任何代码块可以捕获错误,因此您的应用无法对错误做出任何响应。

这意味着最重要的是不要吞下错误,这意味着您需要在某个地方捕获它。在我的两个示例中,您可以看到错误将通过 catch 块传递。

错误吞咽的次要事实是,错误甚至一开始就被抛出。在我看到这一点的应用程序中,很难调试,但我可以看到错误的性质与路由更改时 Vue 组件的卸载和加载有关。例如,如果您在一个组件中调用 this.$router.push(),然后该组件在路由更改正在进行时被销毁,那么您可能会看到这样的错误是合理的。

作为此问题的扩展,如果发生路由更改并且结果组件在 Promise 解决之前尝试从 .push() 事件中读取数据,它也可能会抛出此错误。 await 应该通过指示您的应用程序在读取前等待来停止此类错误。

简而言之,调查这两件事:

    您是否在 this.$router.push() 执行时以某种方式破坏/创建组件? 下一个组件是否可能在路由更改完成之前读取有关路由参数的数据?

如果您发现其中一些可能会发生,请考虑您的数据流,并确保通过驯服异步行为来解决它,而不仅仅是通过抑制错误。在我看来,错误是更大问题的征兆。

在调试期间,将console.log()s 添加到所有组件的created/mounteddestroyed 生命周期方法中,以及与路由更改相关的函数中。您应该能够掌握数据的流动方式。

我怀疑此问题的性质源于在飞行中路线更改期间对this.$route.params 的下游使用。添加大量 console.logs 和/或单步调试器。

【讨论】:

奇怪的是,没有 try catch 并且只有 await await this.$router.push('/account') 'Promise must be proper handling' 错误我已经消失了。 这表明$router.push() 返回了一个promise,并且没有等待,您的代码将继续前进,下游代码会尝试在promise 的结果被解析之前读取它。添加await 会延迟下游代码,因此它会读取已解决的promise,而不是in-flight 的promise。【参考方案3】:

在我的例子中,我只需要在router.push 方法中添加一个catch

router.push(query: newQueryObj)).catch(e => )

查看related issue了解更多详情。

【讨论】:

【参考方案4】:

添加 main.js;

import Router from 'vue-router'
const routerPush = Router.prototype.push
Router.prototype.push = function push(location) 
  return routerPush.call(this, location).catch(error=> error)

或者; npm i vue-router@3.0 -S

【讨论】:

【参考方案5】:

我也遇到了这个问题,将路由器中的 !variable 更改为 variable !== 就可以了。

else if(from.name && !localStorage.token) 
    router.go('/login');

else if(from.name && localStorage.token === '') 
    router.go('/login');

【讨论】:

对我的情况没有帮助。实际上触发的是它上面的块,而不是 else if,因为这发生在用户第一次登录时。 这对我有帮助,但我不清楚这对我有什么帮助/为什么...

以上是关于Uncaught (in promise) undefined - Vue-router的主要内容,如果未能解决你的问题,请参考以下文章

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 Promise [重复]

解决Uncaught (in promise) reason的问题

Uncaught (in Promise) DOMException: play() 只能由用户手势启动

解决Uncaught (in promise) reason的问题

Uncaught (in promise):消息端口在收到响应之前关闭

vue控制台报 Uncaught (in promise) TypeError: