从异步函数设置对象值

时间:2013-06-23 09:24:45

标签: javascript html5

如何在不丢失值的情况下从异步函数设置对象的属性?另一个SO线程上的某个人说任何与这个函数有关的东西都应该保存在函数中。但是,我想从中分配值,并将其分配给对象。我对OOP Js来说有点新鲜,所以这让我很困惑。

我有这个获取用户位置的功能。这个HTML5函数需要一个回调来传递一个位置对象。

function getInfo()
{
    navigator.geolocation.getCurrentPosition(getPos);
}

这是getCurrentPosition()中引用的函数。

function getPos(position)
{
PositionObj.lat = position.coords.latitude;
PositionObj.lon = position.coords.longitude;
}

PositionObj:

var PositionObj = 
{
lat:null,
lon:null,
returnLat: function()
             {
             return this.lat;
             },
returnLon: function()
             {
             return this.lon;
             }
};

当我尝试访问PositionObj的属性时,我得到null,而不是回调分配的新值。我该怎么做呢?我已经尝试过将回调作为对象本身,并将值传递给另一个为对象赋值的函数。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

最重要的问题是:何时您是否正在尝试访问PositionObj的属性?由于整个内容是异步的,因此在检索位置并lat分配位置之前,您在longetPos中看不到任何值。因此,同步的事情如下:

getInfo();
console.log(PositionObj.lat);

绝对不会起作用。 getInfo立即返回 并且不会等待该位置进入。这是一个好的事情:关于异步的整个想法是你不等待(块)直到你得到你的结果。相反,您给函数回调,该函数确保在稍后检索结果时调用它。好莱坞风格:“别叫我,我叫你!”

因此,依赖于getInfo检索的实际位置的任何内容都需要在回调中。这意味着你必须以不同的方式思考和编码 :你需要将你的同步函数分解为更小的函数,这些函数被链接起来作为回调。

在你的情况下,你会把console.log(PositionObj.lat)(或者你想做的任何其他事情)置于(你所谓的)getPos(你可能)想要为这个功能想一个更好的名字。)

这是一个更完整的例子,可以更好地展示这个概念。在线商店的结帐页面可能会有类似的内容:

var position = getPosition(); // using geolocation
var closestShop = getClosestShop(position); // using AJAX to a server-side script
alert("The closest shop is " + closestShop);

但是,所有这些同步调用都会阻止脚本的执行,页面会“冻结”。用户可能会认为他的浏览器崩溃了,这不是一个很棒的用户体验。

如果所有这些操作都是异步的,那么您需要对其进行重组,使其如下所示:

getPosition(function(position) {
    getClosestShop(position, function(closestShop) {
        alert("The closest shop is " + closestShop);
    });
});

这里,每个函数接受一个回调函数,它在结果进入时调用。它们都立即返回,允许脚本继续执行并保持页面响应。当然,没有什么能阻止你从这个回调中启动另一个异步动作,从而有效地将它们链接起来。

事实上,最后一种模式非常流行,因此创建了一种新机制,使其更易于管理:promises。内部工作仍然是相同的(函数接受回调而不是同步阻塞)但它看起来更令人愉快。当您getPositiongetClosestShop返回承诺时,您可以写:

getPosition().then(getClosestShop).then(function(closestShop) {
    alert("The closest shop is " + closestShop);
});