Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 如何使用IcedOfficeScript正确处理错误?_Node.js_Error Handling_Coffeescript_Iced Coffeescript - Fatal编程技术网

Node.js 如何使用IcedOfficeScript正确处理错误?

Node.js 如何使用IcedOfficeScript正确处理错误?,node.js,error-handling,coffeescript,iced-coffeescript,Node.js,Error Handling,Coffeescript,Iced Coffeescript,node.js中的常见做法是将错误消息作为第一个参数返回回调函数。在纯JS中有许多解决这个问题的方法(Promise、Step、seq等),但它们似乎都不能与IC集成。在不损失很多可读性的情况下,处理错误的正确解决方案是什么 例如: # makes code hard to read and encourage duplication await socket.get 'image id', defer err, id if err # ... await Image.findById id,

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

例如:

# 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  # ...

我通过样式和编码惯例来解决这个问题。而且它总是出现。让我们看一下下面的代码片段,再充实一点,这样我们就有了一个可行的函数

my_fn=(cb)->
等待套接字。获取“映像id”,延迟错误,id
如果为err,则返回cb err,null
等待Image.findById id,延迟错误,映像
如果为err,则返回cb err,null
等待检查权限用户、映像、延迟错误、允许
如果为err,则返回cb err,null
cb错误,图像
您完全正确,这很难看,因为您在许多地方短路了代码,您需要记住每次返回时调用cb

您给出的其他代码段产生了错误的结果,因为它们将在需要序列化的地方引入并行性

我个人的ICS编码惯例是:(1)一个函数只返回一次(控制从末尾脱落);(2)尝试在相同的缩进级别处理所有错误。用我喜欢的风格改写你的作品:

my_fn=(cb)->
等待套接字。获取“映像id”,延迟错误,id
等待Image.findById id,延迟错误,镜像除非错误?
等待检查\u权限用户、图像、延迟错误、允许,除非错误?
cb错误,图像
如果socket.get调用中出现错误,则需要检查两次错误,显然两次都会失败。我不认为这是世界末日,因为它使代码更干净

或者,您可以执行以下操作:

my_fn=(autocb)->
等待套接字。获取“映像id”,延迟错误,id
如果为err,则返回[err,null]
等待Image.findById id,延迟错误,映像
如果为err,则返回[err,null]
等待检查权限用户、映像、延迟错误、允许
返回[错误,图像]
如果您使用autocb,这不是我最喜欢的ICS功能,那么每当您返回/短路出函数时,编译器将为您调用autocb。根据经验,我发现这种构造更容易出错。例如,假设您需要在函数开始时获取一个锁,现在需要释放它n次。其他人可能不同意

另一个注释,在下面的评论中指出
autocb
的工作原理类似于
return
,因为它只接受一个值。如果要像本例中那样返回多个值,则需要返回数组或字典<代码>延迟执行分解分配以帮助您完成以下任务:

等待我的延迟[err,image]
正如在IcedCoffeeScript存储库的中所讨论的,还有一种基于iced样式连接器的技术,它是将回调/延迟作为输入并返回另一个回调/延迟的函数

假设您的项目具有回调参数的标准顺序:第一个参数始终是error,成功时为null。此外,进一步假设您希望在出现错误的第一个迹象时保留函数

第一步是制作一个连接器,我称之为“ErrorShortCircuiter”或“ESC”:

其实现方式如下:

make_esc = (gcb, desc) -> (lcb) ->
    (err, args...) ->
        if not err? then lcb args...
        else if not gcb.__esc
            gcb.__esc = true
            log.error "In #{desc}: #{err}"
            gcb err

查看它正在做什么,考虑一个如何使用它的例子:

my_fn = (gcb) ->
    esc = make_esc gcb, "my_fn"
    await socket.get 'image id', esc defer id
    await Image.findById id, esc defer image
    await check_permissions user, image, esc defer permitted
    gcb null, image
此版本的
my\u fn
首先生成一个ErrorShortCircuiter(或
esc
),其工作有两方面:(1)使用error对象触发
gcb
;和(2)记录错误发生的位置和错误是什么的消息。显然,您应该根据您的设置改变确切的行为。然后,所有后续调用库函数的回调将像往常一样由
defer
生成,然后通过
esc
连接器运行,这将改变回调的行为。新的行为是在出现错误时调用函数的
gcb
global,并在成功时让当前
等待
块完成。此外,在成功的情况下,不需要处理空错误对象,因此只填充后续的插槽(如
id
image
、以及
允许的


这项技术非常强大,可以定制。关键思想是,
defer
生成的回调实际上是连续的,可以改变整个程序的后续控制流。它们可以在库中执行此操作,因此您可以获得许多不同类型的应用程序所需的错误行为,这些应用程序调用具有不同约定的库。

谢谢,出于某种原因,并行运行这种顺序命令对我来说很有效,我将在我这方面解决这个问题,而且似乎“。。。“除非”是一个足够好的解决方案。另外,关于autocb,我以前没有听说过该功能,它在哪里有文档记录?谢谢,最好在自述文件中的某个地方有一个指向该文档的链接,因为它仍然指向稍微过时的pageautocb,它不适用于节点样式的回调。只能返回一个值。上面的代码将生成一个错误。看,你是对的,谢谢你指出这一点。我通过返回对来“修复”这个例子。请参阅我对这个问题的评论。您的错误必须是错误对象,而不是普通字符串。
my_fn = (gcb) ->
    esc = make_esc gcb, "my_fn"
    await socket.get 'image id', esc defer id
    await Image.findById id, esc defer image
    await check_permissions user, image, esc defer permitted
    gcb null, image