jjzjj

javascript - Vue.js:Nuxt 错误处理

coder 2024-05-09 原文

使用 vuex 设置错误处理有点困难。似乎有很多方法可以做到这一点,而且关于正确错误处理的文档很少。我一直在尝试四种替代方案,但还没有找到令人满意的解决方案。


备选方案 1 - 捕获和处理组件上的错误

pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            }).catch((error) {
                // handle error in component
            });
        },
    },
}

store/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
        });
    },
}

优点

  • 嗯。

缺点

  • 未在 vuex 中处理和存储的错误。
  • 在组件方法中引入了大量样板代码。

备选方案 2 - 在 vuex 中捕获和处理错误

pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            });
        },
    },
}

store/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
        }).catch((error) => {
            // store error in application state
            commit('SET_ERROR', error);
        });
    },
}

优点

  • 错误对象可以通过任何组件的 vuex 访问
  • 可以在布局中使用 react 性错误组件,当错误状态发生变化时会显示出来。

缺点

  • 我不确定是否有一种方法可以跟踪错误的来源,即错误是从哪个组件抛出的。

备选方案 3 - 使用 axios 拦截器捕获错误

plugins/axios.js:

export default function({ $axios, store }) {
    $axios.onError(error => {
        store.dispatch('setError', error);
    });
}

pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            });
        },
    },
}

store/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
        });
    },
}

优点

  • 全局错误处理
  • 无需捕获 vuex 或组件中的错误
  • 没有样板代码

缺点

  • 所有异常都未处理,这意味着未捕获非 axios 错误。

备选方案 4 - 自定义错误插件

我一直在尝试实现一个捕获所有异常的自定义插件,但我没有成功地让它工作。

plugins/catch.js:

export default (ctx, inject) => {
    const catchPlugin = function (func) {
        return async function (args) {
            try {
                await func(args)
            } catch (e) {
                return console.error(e)
            }
        }
    };
    ctx.$catch = catchPlugin;
    inject('catch', catchPlugin);
}

pages/login.vue:

export default {
    methods: {
        onLogin: this.$catch(async function () {
            await this.$store.dispatch('auth/login', { email: this.email, password: this.password });
            this.$router.push('/home');
        }),
    },
}

优点

  • 没有样板文件。
  • 插件中捕获的所有错误。

缺点

  • 我做不到。 :(

我的印象是 vue/nuxt 中缺少关于错误处理的文档。谁能得到第四种工作选择?这会是理想的吗?还有其他选择吗?什么是常规?

感谢您的宝贵时间!

最佳答案

选项 #4 不起作用的原因是你返回了一个永远不会执行的函数:

function catchPlugin(outerFunction) {
   return function async innerFunction(args) {
     try {
       const data = await outerFunction(args);
       return { data } 
     } catch (error) {
       return { error }
     }
   }
}

用法:

const execute = catchPlugin((args) => {
  // do something
})

execute('myArgument');

如您所见,您还需要执行内部函数,以使您的示例工作:

onLogin: this.$catch(async function () {
    await this.$store.dispatch('auth/login', { email: this.email, password: this.password });
    this.$router.push('/home');
})(), // mind the () :-)

但是...我相信在组件中处理错误并不是一件坏事,因为这与您的 View 组件紧密耦合。例如,考虑一个登录组件,我们现在看到的是一个全局错误处理程序 (toastr),如果用户名/密码不正确,它会显示提示信息。根据我的经验,这不是最好的行为,它是一个很好的起点,但更好的做法是在组件附近添加错误消息,显示究竟出了什么问题。这意味着您将始终必须在组件本身中添加错误处理(与 UI 相关)。

我们公司的同事也在为同一产品工作而苦苦挣扎。一种是添加错误处理,另一种不是。在我看来,唯一的解决方案是教育开发人员始终添加正确的错误处理。 async/await 的语法还不错:

methods: {
   async login (email, password) {
      try {
         await this.$store.dispatch('auth/login', { email, password })
         // do something after login
      } catch (error) {
         // handle error
      }
   }
}

关于您的 con 的最后一件事:未在 vuex 中处理和存储错误。。为什么这是一个骗局?您是否需要在全局范围内提供错误信息?我看到的很多是人们在 vuex 中放置了很多仅在组件本身中使用的无用状态。拥有本地组件状态也不错。既然是关于登录的,这个错误应该只有登录组件才知道。

关于javascript - Vue.js:Nuxt 错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51247371/

有关javascript - Vue.js:Nuxt 错误处理的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  4. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  5. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  6. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  7. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  8. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  9. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  10. arrays - 这是 Ruby 中 Array.fill 方法的错误吗? - 2

    这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]

随机推荐