如何在不丢失值的情况下从异步函数设置对象的属性?另一个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,而不是回调分配的新值。我该怎么做呢?我已经尝试过将回调作为对象本身,并将值传递给另一个为对象赋值的函数。任何帮助将不胜感激!
答案 0 :(得分:1)
最重要的问题是:何时您是否正在尝试访问PositionObj
的属性?由于整个内容是异步的,因此在检索位置并lat
分配位置之前,您在lon
或getPos
中看不到任何值。因此,同步的事情如下:
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。内部工作仍然是相同的(函数接受回调而不是同步阻塞)但它看起来更令人愉快。当您getPosition
和getClosestShop
返回承诺时,您可以写:
getPosition().then(getClosestShop).then(function(closestShop) {
alert("The closest shop is " + closestShop);
});