看看发生了什么事是你正在处理异步代码,如果它是同步的。某些调试输出可能会帮助您将此可视化:
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(或CoffeeScript)中的同步函数中包装异步函数;甚至运行一个无限循环,直到你的回调被调用都不起作用,因为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是必读的。异步性需要一些习惯,但与多线程相比,它的优势是惊人的。
您描述的范围问题已成为StackOverflow上最常见的CoffeeScript问题;请参阅http://stackoverflow.com/questions/6089992/cant-find-variable-error-with-rails-3-1-and-coffeescript和其他几个。 –