如何使用IcedCoffeeScript正确处理错误?

And*_*rew 8 error-handling node.js coffeescript iced-coffeescript

node.js中的常见做法是将错误消息作为回调函数的第一个参数返回.纯JS(Promise,Step,seq等)中有许多解决这个问题的方法,但它们似乎都不能与ICS集成.什么是正确的解决方案来处理错误而不会失去很多可读性?

例如:

# makes code hard to read and encourage duplication
await socket.get 'image id', defer err, id
if err # ...
await Image.findById id, defer err, image
if err # ...
await check_permissions user, image, defer err, permitted
if err # ...


# will only handle the last error
await  
  socket.get 'image id', defer err, id
  Image.findById id, defer err, image
  check_permissions user, image, defer err, permitted

if err  # ...


# ugly, makes code more rigid
# no way to prevent execution of commands if the first one failed
await  
  socket.get 'image id', defer err1, id
  Image.findById id, defer err2, image
  check_permissions user, image, defer err3, permitted

if err1 || err2 || err3  # ...
Run Code Online (Sandbox Code Playgroud)

Max*_*ohn 12

我通过样式和编码约定来解决这个问题.它确实一直出现.让我们把你的片段放在下面,充实一点,以便我们有一个可行的功能.

my_fn = (cb) ->
  await socket.get 'image id', defer err, id
  if err then return cb err, null
  await Image.findById id, defer err, image
  if err then return cb err, null
  await check_permissions user, image, defer err, permitted
  if err then return cb err, null
  cb err, image
Run Code Online (Sandbox Code Playgroud)

你是完全正确的,这是丑陋的,因为你在很多地方短路代码,你需要记住每次返回时调用cb.

您提供的其他片段会产生不正确的结果,因为它们会引入需要序列化的并行性.

我的个人ICS编码约定是:(1)从函数返回一次(控件从结尾处退出); (2)尝试在同一级别的缩进处理错误.以我喜欢的方式重写你拥有的东西:

my_fn = (cb) ->
  await socket.get 'image id', defer err, id 
  await Image.findById id, defer err, image                   unless err?
  await check_permissions user, image, defer err, permitted   unless err?
  cb err, image
Run Code Online (Sandbox Code Playgroud)

如果socket.get调用出错,则需要检查错误两次,两次都会失败.我不认为这是世界末日,因为它使代码更清晰.

或者,您可以这样做:

my_fn = (autocb) ->
  await socket.get 'image id', defer err, id
  if err then return [ err, null ]
  await Image.findById id, defer err, image
  if err then return [ err, null ]
  await check_permissions user, image, defer err, permitted
  return [ err, image ]
Run Code Online (Sandbox Code Playgroud)

如果你使用autocb,这不是我最喜欢的ICS功能,那么只要你返回/短路函数,编译器就会为你调用autocb.我觉得这种结构更容易出错.例如,想象一下你需要在函数开始时获取一个锁,现在你需要释放它n次.其他人可能不同意.

另外一点,在评论中指出. autocb就像return它只接受一个值一样.如果要在此示例中返回多个值,则需要返回数组或字典. defer做解构任务,以帮助你在这里:

await my_fn defer [err, image]
Run Code Online (Sandbox Code Playgroud)