Javascript 等待条件为真?

Javascript 等待条件为真?,javascript,geolocation,Javascript,Geolocation,我在JavaScript中使用了navigator.geolocation.watchPosition,我希望找到一种方法来处理用户可能在watchPosition找到其位置之前提交依赖于位置的表单的可能性 理想情况下,用户会定期看到“等待位置”消息,直到获得位置,然后表单才会提交 然而,我不知道如何在JavaScript中实现它,因为它缺少wait函数 当前代码: var current_latlng = null; function gpsSuccess(pos){ //consol

我在JavaScript中使用了
navigator.geolocation.watchPosition
,我希望找到一种方法来处理用户可能在
watchPosition
找到其位置之前提交依赖于位置的表单的可能性

理想情况下,用户会定期看到“等待位置”消息,直到获得位置,然后表单才会提交

然而,我不知道如何在JavaScript中实现它,因为它缺少
wait
函数

当前代码:

var current_latlng = null;
function gpsSuccess(pos){
    //console.log('gpsSuccess');  
    if (pos.coords) { 
        lat = pos.coords.latitude;
        lng = pos.coords.longitude;
    }
    else {
        lat = pos.latitude;
        lng = pos.longitude;
    }
    current_latlng = new google.maps.LatLng(lat, lng);
}
watchId = navigator.geolocation.watchPosition(gpsSuccess,
                  gpsFail, {timeout:5000, maximumAge: 300000});
$('#route-form').submit(function(event) {
    // User submits form, we need their location...
    while(current_location==null) {
        toastMessage('Waiting for your location...');
        wait(500); // What should I use instead?
    }
    // Continue with location found...
});
您将要使用:


。。。其中
getLocation
查找您的位置。

您可以使用超时来尝试重新提交表单:

$('#route-form').submit(function(event) {
    // User submits form, we need their location...
    if(current_location==null) {
        toastMessage('Waiting for your location...');
        setTimeout(function(){ $('#route-form').submit(); }, 500); // Try to submit form after timeout
        return false;
    } else {
        // Continue with location found...
    }
});

就我个人而言,我使用了一个
waitfor()
函数,它封装了一个
setTimeout()

我以以下方式使用我的
waitfor()
函数:

var _TIMEOUT = 50; // waitfor test rate [msec]
var bBusy = true;  // Busy flag (will be changed somewhere else in the code)
...
// Test a flag
function _isBusy() {
    return bBusy;
}
...

// Wait until idle (busy must be false)
waitfor(_isBusy, false, _TIMEOUT, 0, 'play->busy false', function() {
    alert('The show can resume !');
});

这正是承诺被发明和实现的原因(自从OP提出他的问题以来)


查看所有各种实现,例如promisejs.org

使用Promise的现代解决方案

function waitFor(conditionFunction) {

  const poll = resolve => {
    if(conditionFunction()) resolve();
    else setTimeout(_ => poll(resolve), 400);
  }

  return new Promise(poll);
}
waitFor(_ => flag === true)
  .then(_ => console.log('the wait is over!'));
用法

function waitFor(conditionFunction) {

  const poll = resolve => {
    if(conditionFunction()) resolve();
    else setTimeout(_ => poll(resolve), 400);
  }

  return new Promise(poll);
}
waitFor(_ => flag === true)
  .then(_ => console.log('the wait is over!'));

async function demo() {
  await waitFor(_ => flag === true);
  console.log('the wait is over!');
}
参考资料



试着像这样使用
setInterval
clearInterval

无功电流\u latlng=null;
功能GPSSUCESS(pos){
//console.log('gpssucess');
如果(位置坐标){
纬度=位置坐标纬度;
lng=位置坐标经度;
}否则{
纬度=位置纬度;
lng=位置经度;
}
current_latlng=新的google.maps.latlng(lat,lng);
}
watchId=navigator.geolocation.watchPosition(gpssucess,
gpsFail{
超时:5000,
最高限额:300000
});
$(“#路由表单”).submit(函数(事件){
//用户提交表单,我们需要他们的位置。。。
//每半秒检查一次状态
var watch=setInterval(任务,500)
功能任务(){
如果(当前时间!=null){
间隔时间(手表)
手表=假
返回回调()
}否则{
toastMessage('等待您的位置…');
}
}
函数回调(){
//继续查找找到的位置。。。
}
});

异步思考。查找
setTimeout
。异步和递归地调用setTimeout,直到当前\u latlng有一些值为止。在责怪它之前,先理解语言。当然没有“缺少”等待功能。@Richard是的,但无论你做什么,都会使用超时。当Javascript以任何方式(几乎全部)连续运行时,您会惊讶于它会占用多少CPU资源。由于异步性,它不是严格意义上的函数调用递归,但从代码的角度来看,这是肯定的。您也可以在
gpsFail
中放置标志,然后在
checkAndSubmit
中检查并显示正确的消息。它需要是一个字符串,否则超时值将为.submit。我想您可以执行函数(){return$('#route form').submit();}。我想那会有用的。我根本不懂你的第一句话。是的,函数表达式是正确的方法。:)可能是过度优化,但不是
function(){$('#路由表单')。submit()}
,你不能执行
$('#路由表单')。submit
?是的,你也可以这样做,可能会更干净一些。别忘了
waitfor()
函数的末尾,但是如果在最后一个(也就是初始的)waitfor调用下面有更多的代码,那么该代码不会继续执行,直到它暂停,因为是时候运行第一个预定的setTimeout调用了吗?最初waitfor只是一个函数,它设置setTimeout调用,然后返回。您的代码将一直监视,直到值发生变化,但直到值发生变化它才会阻塞。这是这个问题唯一正确的答案,而且它在之前的投票数为0真的令人担忧now@HansWesterbeek可能是因为承诺的概念是一个广泛的主题。我已经有一种感觉,我应该使用一个承诺,但这个答案太模糊了,帮不了我。
class App extends React.Component {

componentDidMount() {
   this.processToken();

}
 processToken = () => {
    try {
        const params = querySearch(this.props.location.search);
        if('accessToken' in params){
            this.setOrderContext(params);
            this.props.history.push(`/myinfo`);
        }
    } catch(ex) {
      console.log(ex);
    }
    }

   setOrderContext (params){
     //this action calls a reducer and put the token in session storage
     this.props.userActions.processUserToken({data: {accessToken:params.accessToken}});
}

render() {
    return (

        <Switch>
            //myinfo component needs accessToken to retrieve my info
            <Route path="/myInfo" component={InofUI.App} />
        </Switch>

    );
}
componentDidMount() {
        this.retrieveMyInfo();
    }

    retrieveMyInfo = async () => {
        await this.untilTokenIsSet();
        const { location, history } = this.props;
        this.props.processUser(location, history);
    }

    untilTokenIsSet= () => {
        const poll = (resolve) => {
            const { user } = this.props;
            const { accessToken } = user;
            console.log('getting accessToken', accessToken);
            if (accessToken) {
                resolve();
            } else {
                console.log('wating for token .. ');
                setTimeout(() => poll(resolve), 100);
            }
        };
        return new Promise(poll);
    }