从异步函数设置对象值

Set object values from asynchronous function

本文关键字:对象 设置 函数 异步      更新时间:2023-09-26

如何在不丢失值的情况下从异步函数设置对象的属性?另一个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,而不是回调分配的新值。我该怎么做?我尝试过将回调本身作为对象,并将值传递给另一个为对象赋值的函数。任何帮助都将不胜感激!

最重要的问题是:何时尝试访问PositionObj的属性?由于整个过程是异步的,在检索到位置并由getPos分配之前,您不会在latlon中看到任何值

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);
    });
});

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

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

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