假设我们有一个在用户登录时运行的操作(express,node)。 这是有效的代码,使用大量回调编写:
checkIfEmailAndPasswordAreSet(email, password, (error, response) => {
if (error) return errorResponse(403, 'validation error', error)
findUserByEmail(email, (error, user) => {
if (error) return errorResponse(500, 'db error', error)
if (!user) return errorResponse(403, 'user not found')
checkUserPassword(user, password, (error, result) => {
if (error) return errorResponse(500, 'bcrypt error', error)
if (!result) return errorResponse(403, 'incorrect password')
updateUserLastLoggedIn(user, (error, response) => {
if (error) return errorResponse(500, 'db error', error)
generateSessionToken(user, (error, token) => {
if (error) return errorResponse(500, 'jwt error', error)
return successResponse(user, token)
})
})
})
})
})
我想使用 async/await 重写这段代码并避免回调 hell 。怎么做?
第一次尝试可能是这样的:
try {
await checkIfEmailAndPasswordAreSet(email, password)
const user = await findUserByEmail(email)
if (!user) throw new Error('user not found')
const result = await checkUserPassword(user, password)
if (!result) throw new Error('incorrect password')
await updateUserLastLoggedIn(user)
const token = await generateSessionToken(user)
return successResponse(user, token)
} catch (e) {
// How to handle the error here?
}
我想保持正确的错误处理,也就是说,如果错误是在 checkUserPassword 方法中抛出的,我希望响应包含有关此的信息。 catch方法应该写什么?
例如,我可以像这样将每条指令包装到它自己的 try/catch block 中:
try {
let user, result
try {
await checkIfEmailAndPasswordAreSet(email, password)
} catch (error) {
throw new Error('This error was thrown in checkIfEmailAndPasswordAreSet')
}
try {
user = await findUserByEmail(email)
} catch (error) {
throw new Error('This error was thrown in findUserByEmail')
}
if (!user) throw new Error('user not found')
...
} catch (error) {
return errorResponse(error)
}
但是这段代码.. 可能不是回调 hell ,但我会称之为 try/catch hell 。与带有回调的原始老式代码相比,它至少需要多 2 倍的行。如何重写它以使其更短并利用 async/await?
最佳答案
没有 easy handling of individual errors使用try/catch。
我可能会编写一些辅助函数来促进简单的错误抛出:
function error(code, msg) {
return e => {
e.status = code;
e.details = msg;
throw e;
};
}
function ifEmpty(fn) {
return o => o || fn(new Error("empty"));
}
然后使用标准的 promise 方法:
try {
await checkIfEmailAndPasswordAreSet(email, password)
.catch(error(403, 'validation error'));
const user = await findUserByEmail(email)
.then(ifEmpty(error(403, 'user not found')), error(500, 'db error', error));
await checkUserPassword(user, password)
.then(ifEmpty(error(403, 'incorrect password')), error(500, 'bcrypt error'));
await updateUserLastLoggedIn(user)
.catch(error(500, 'db error'));
const token = generateSessionToken(user)
.catch(error(500, 'jwt error'));
return successResponse(user, token);
} catch(err) {
errorResponse(err.status, err.details, err);
}
关于javascript - 异步/等待正确的错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48475999/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
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
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我遵循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
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我正在尝试编写一个将文件上传到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
我克隆了一个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
在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
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie