Javascript 等到条件为真?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7193238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:17:41  来源:igfitidea点击:

Wait until a condition is true?

javascriptgeolocation

提问by Richard

I'm using navigator.geolocation.watchPositionin JavaScript, and I want a way to deal with the possibility that the user might submit a form relying on location before watchPositionhas found its location.

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

Ideally the user would see a 'Waiting for location' message periodically until the location was obtained, then the form would submit.

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

However, I'm not sure how to implement this in JavaScript given its lack of a waitfunction.

但是,由于缺少wait函数,我不确定如何在 JavaScript 中实现它。

Current code:

当前代码:

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

采纳答案by Chris Pickett

You could use a timeout to try to re-submit the form:

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

$('#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...
    }
});

回答by Martin Mohnhaupt

Personally, I use a waitfor()function which encapsulates a setTimeout():

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

//**********************************************************************
// function waitfor - Wait until a condition is met
//        
// Needed parameters:
//    test: function that returns a value
//    expectedValue: the value of the test function we are waiting for
//    msec: delay between the calls to test
//    callback: function to execute when the condition is met
// Parameters for debugging:
//    count: used to count the loops
//    source: a string to specify an ID, a message, etc
//**********************************************************************
function waitfor(test, expectedValue, msec, count, source, callback) {
    // Check if condition met. If not, re-check later (msec).
    while (test() !== expectedValue) {
        count++;
        setTimeout(function() {
            waitfor(test, expectedValue, msec, count, source, callback);
        }, msec);
        return;
    }
    // Condition finally met. callback() can be executed.
    console.log(source + ': ' + test() + ', expected: ' + expectedValue + ', ' + count + ' loops.');
    callback();
}

I use my waitfor()function in the following way:

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

回答by Lightbeard

Modern solution using Promise

使用 Promise 的现代解决方案

function waitFor(conditionFunction) {

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

  return new Promise(poll);
}

Usage

用法

waitFor(_ => flag === true)
  .then(_ => console.log('the wait is over!'));

or

或者

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

References
Promises
Arrow Functions
Async/Await

参考
Promise
箭头函数
Async/Await

回答by Nicole

You'll want to use setTimeout:

你会想要使用setTimeout

function checkAndSubmit(form) {
    var location = getLocation();
    if (!location) {
        setTimeout(checkAndSubmit, 500, form); // setTimeout(func, timeMS, params...)
    } else {
        // Set location on form here if it isn't in getLocation()
        form.submit();
    }
}

... where getLocationlooks up your location.

...在哪里getLocation查找您的位置。

回答by Ben Wheeler

This is precisely what promises were invented and implemented (since OP asked his question) for.

这正是 Promise 的发明和实现(因为 OP 提出了他的问题)。

See all of the various implementations, eg promisejs.org

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

回答by Sajjad

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>

    );
}

And then inside InofUI.App

然后在 InofUI.App 里面

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

回答by openwonk

Try using setIntervaland clearIntervallike this...

尝试使用setIntervalclearInterval喜欢这个......

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...
    // Checks status every half-second
    var watch = setInterval(task, 500)

    function task() {
        if (current_latlng != null) {
            clearInterval(watch)
            watch = false
            return callback()
        } else {
            toastMessage('Waiting for your location...');

        }
    }

    function callback() {
        // Continue on with location found...
    }
});