2011-07-26 71 views
3

在我看来,我想:如何用Coffeescript和Rails 3.1定义回调函数?

:coffeescript 
    Gmap('#canvas').getAddressBounds request.term 

这是在maps.js.coffee定义为

Gmap = (mapId) -> 
    getAddressBounds: (address) -> 
    data = [] 
    $(mapId).gmap3 
     action: 'getAddress' 
     address: address 
     callback: (results) -> 
     return unless results 
     data = $.map results, (item) -> 
      bounds: item.geometry.bounds 
    data 

这不工作,虽然。首先,有一个范围问题。 Gmap函数对视图中的脚本不可见。如果我将代码直接添加到视图中,则Gmap可见,但数据总是以[]形式返回。

+0

您描述的范围问题已成为StackOverflow上最常见的CoffeeScript问题;请参阅http://stackoverflow.com/questions/6089992/cant-find-variable-error-with-rails-3-1-and-coffeescript和其他几个。 –

回答

5

看看发生了什么事是你正在处理异步代码,如果它是同步的。某些调试输出可能会帮助您将此可视化:

Gmap = (mapId) -> 
    getAddressBounds: (address) -> 
    data = [] 
    console.log '1: Calling gmap3' 
    $(mapId).gmap3 
     action: 'getAddress' 
     address: address 
     callback: (results) -> 
     console.log '3: Callback called' 
     return unless results 
     data = $.map results, (item) -> 
      bounds: item.geometry.bounds 
    console.log '2: Returning data' 
    data 

当您传递回调时,它可能随时被调用。如果在gmap3函数中调用它,则在返回之前确实会设置data。但gmap3使用回调返回结果而不是仅仅返回的原因是该函数是异步的,特别是当服务器响应您的查询时它会调用回调函数。 JavaScript执行事件的方式,这意味着您的回调有保证而不是被调用,直到所有代码完成执行。

无法在JavaScript(或Cof​​feeScript)中的同步函数中包装异步函数;甚至运行一个无限循环,直到你的回调被调用都不起作用,因为JS运行时再一次处理事件,比如服务器响应(甚至用户输入事件),直到所有的代码完成执行。因此,所有你能做的就是改变你的功能,也使用回调:

Gmap = (mapId) -> 
    getAddressBounds: (address, cb) -> 
    $(mapId).gmap3 
     action: 'getAddress' 
     address: address 
     callback: (results) -> 
     return unless results 
     cb $.map results, (item) -> 
      bounds: item.geometry.bounds 

然后调用它像这样:

Gmap('#canvas').getAddressBounds request.term, (data) -> console.log data 

我聊多一点关于my CoffeeScript book的JS事件模型。另外,John Resig的How JavaScript Timers Work是必读的。异步性需要一些习惯,但与多线程相比,它的优势是惊人的。

2

变化 GMAP = ... 到 window.Gmap = ....

将解决这个问题。原因是coffeescript将所有内容都包含在一个匿名函数中。如果你想有一个更全面的功能模块系统,这里有

https://github.com/jashkenas/coffee-script/wiki/Easy-modules-with-coffeescript

+0

这解决了范围问题,但不是返回'[]'的问题。 –

+0

你说得对,我只看到最明显的问题。可惜StackOverflow不会让OP选择两个答案;) – bradgonesurfing

相关问题