【问题标题】:Titanium and Javascript anonymous function scopeTitanium 和 Javascript 匿名函数作用域
【发布时间】:2011-12-15 14:42:05
【问题描述】:

我正在尝试在钛中调用 forwardGeocoder 函数,但在检索结果时遇到了一些问题,请考虑以下代码:-

x = 0;

Ti.Geolocation.forwardGeocoder(startTextFieldContents, function(evt) {
    var startPin = Ti.Map.createAnnotation({
        longitude   :   evt.longitude,
        latitude    :   evt.latitude,
        pincolor    :   Ti.Map.ANNOTATION_GREEN
    });
    
    var startPinLocation = {
        longitude       : evt.longitude,
        latitude        : evt.latitude
    }
    
    mapview.addAnnotation(startPin);
    x = 1;
});

Ti.API.log('X = ' + x);

如果您查看 X,当我将其注销时,它始终等于 0,即使我在我的匿名函数中将其设置为 1,并且因为这是一个以匿名函数作为参数的函数调用,我我正在努力弄清楚如何检索该值并使其在 forwardGeocoder 之外可用。

为了解决这个问题,根据这篇文章中所说的,我使用了以下代码:

var completed = 0;
        
        Ti.Geolocation.forwardGeocoder(startTextFieldContents, function(evt) {
            var startPin = Ti.Map.createAnnotation({
                longitude   :   evt.longitude,
                latitude    :   evt.latitude,
                pincolor    :   Ti.Map.ANNOTATION_GREEN
            });
            
            startPinLocation = {
                longitude       : evt.longitude,
                latitude        : evt.latitude
            }
            
            mapview.addAnnotation(startPin);
            ++completed;
            
            if (completed === 1) {
                Ti.Geolocation.forwardGeocoder(finishTextFieldContents, function(evt) {
                    var finishPin = Ti.Map.createAnnotation({
                        longitude   :   evt.longitude,
                        latitude    :   evt.latitude,
                        pincolor    :   Ti.Map.ANNOTATION_RED
                    });
            
                    finishPinLocation = {
                        longitude       : evt.longitude,
                        latitude        : evt.latitude
                    }
            
                    mapview.addAnnotation(finishPin);
                    
                    mapview.addRoute({
                        name : 'Route',
                        points : [startPinLocation, finishPinLocation],
                        color : 'green',
                        width : 1
                    });
                    
                });
            }
        });

【问题讨论】:

  • 这就像我评论的你的最后一个问题。它是异步的。因此,您必须开始使用事件驱动模型,而不是像您习惯的那样让您的代码逐行工作。当从服务器获取数据时,该值将在某个时间点可用。为此,您传入一个函数,从该函数中可以使用该值,然后将其传递给所有其他代码。然后,您的日志(以及值的使用)必须来自您传入的匿名函数
  • 我明白你在说什么,在我之前的问题中,我能够在异步事件函数中使用我的日志来获取我的结果,这里的问题是我实际上正在运行两个 forwardGeocoders,一个对于开始位置和结束位置,然后我想将它们传递给另一个函数,该函数将计算它们之间的路线,所以关键问题是我需要可用的开始和结束位置变量,但它们在单独的事件,所以看来我可以到达一个,但不能到达另一个。
  • 您必须将它们全部放在一起。找到开始位置后,找到结束位置。找到结束位置后,您可以计算路线,因为您拥有所有可用数据。
  • 尝试改变你的范式。同意,这是一个稍微棘手的问题,所以让我们想一些解决方案。我将在下面发布一些建议,同时,用您评论中的详细信息更新问题。
  • @Juhana 这是我最初的想法,但问题是它们仍然不能同时提供给彼此。

标签: javascript dom-events titanium


【解决方案1】:

您可以按照 Juhana 的建议嵌套调用。问题是这很慢。您等待来自服务器的往返,然后才开始下一次往返,并且只有在 2 次 同步(即非并行)往返之后,您才执行所需的任务。如果数据相互依赖,这将是必要的,尽管听起来它们不是

因此,您可以执行以下操作:

var completed = 0, values = [];

function handle(data){
   values.push(data);
   ++completed;
   if (completed === 2) {
      dataReadySoLetsDoStuff();
   }
}

fetchFromServer(params1, handle);
fetchFromServer(params2, handle);

function dataReadySoLetsDoStuff() {
   // both values are ready
}

你知道它是如何异步工作的吗?有一个小问题是您无法区分这些值,因为它们的顺序没有得到保证,但您可以轻松更改 handle(例如,currying、binding 或 wrapping)来解决这个问题。

您可以使用其他方法,尽管它们都基于相同的想法 - 计算已完成的任务,直到我保证全部完成,然后执行我们想要执行的任务...

【讨论】:

  • 是的,这就是我正在考虑的方式,但我看到这样做的各种问题,主要是速度问题会是一个问题,我仍然不确定我会不会能够同时从 forwardGeocoder 获取两个位置。
  • @bagwaa,我没有看到任何问题,更不用说“各种”问题了。什么速度问题?
  • 我所指的速度问题是“问题在于这很慢。您等待来自服务器的往返,然后才开始下一次往返”
  • 我想我现在已经根据这里的建议进行了排序,基本上,嵌套它们并检查事件是否完成,然后发布我最终得到的结果。
  • @bagwaa,尽管我建议不要嵌套调用,因为它们是独立的,你可以随意做任何你想做的事情。您的解决方案将起作用,尽管它不需要完成计数即可工作。您可以删除该变量 - 嵌套会为您解决这个问题,但代价是 UX 变慢。
猜你喜欢
  • 2011-12-11
  • 2011-03-11
  • 2011-06-22
  • 2017-08-13
  • 2011-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多