JS承诺内部承诺

时间:2017-01-04 09:14:56

标签: javascript geolocation promise async-await es6-promise

应该在3次尝试中检索位置的getLocation()函数返回undefinednavigator.geolocation.getCurrentPosition()返回正确的位置,但问题在于承诺处理。

问题显然是我在承诺里面的承诺。我不允许在已声明为await的{​​{1}}内使用geolocate()关键字。

原始电话:

async

var getLocationPromise = this.getLocation(); // Do something... location = await getLocationPromise;

getLocation()

async getLocation() { return new Promise((resolve, reject) => { var geolocate; for (let i=0; i<3; i++) { geolocate = this.geolocate(); try { var location = geolocate;//CAN'T USE AWAIT INSIDE ASYNC... resolve(location); } catch(err) { continue; } } reject("Max geolocation attempts"); }); }

geolocate()

2 个答案:

答案 0 :(得分:2)

只要下面的函数声明为async

var getLocationPromise = this.getLocation();
// Do something...
location = await getLocationPromise;

它应该没问题

查看getLocation / geolocate,除非你需要一个单独的geolocate方法,它们应该能够组合并简化为

getLocation() {
    var geolocate = () =>
        new Promise((resolve, reject) => 
            navigator.geolocation.getCurrentPosition(resolve, reject, {
                enableHighAccuracy: true,
                timeout: 20000,
                maximumAge: 1000
            });
        );
    // this function will "retry" the supplied function (fn) cont times
    var limitedPromiseRetry = (fn, cont) => fn().catch(err => cont > 0 ? limitedPromiseRetry(fn, cont-1) : Promise.reject('Max number of geolocation attempts'));
    return limitedPromiseRetry(geolocate, 3);
}

答案 1 :(得分:0)

异步并等待

如果没有await关键字,则不能在函数 中使用async。因此发生错误是因为执行程序函数是 not async

var getLocation = async function(){ // <-- this function has "async" keyword, but ...
    return new Promise( function( resolve, reject ){ // <-- ... this "executor" function has no "async" keyword.
        var value = await geolocate();               // <-- ERROR: await is only valid in async function.
        resolve( value );
    })
};

但是您不应该将promise执行者设为async函数。
有关更多信息,请参见https://eslint.org/docs/rules/no-async-promise-executor

new Promise( async function( resolve, reject ){ // <-- BAD ! Don't do it !
   ...
})

没有嵌套的承诺

但是由于getLocation已经是一个承诺,因此您根本不需要嵌套的new Promise( ... )

var getLocation = async function(){ // <-- "async" makes a function to be a promise
    var value = await geolocate();

    // "return value" inside async function is "the same" as
    // "resolve( value )" in a promise
    return value;
};

因此,从理论上讲,您可以通过以下方式解决您的问题(尽管可能有更好的解决方法。有关异步函数内部的“拒绝”,另请参见How to reject in async/await syntax?)。

var getLocation = async function(){
    for( let i = 0; i < 3; i++ ){
        try {
            console.log('try ...', i);
            var location = await geolocate(i);
            console.log('... success');
            return location;
        } catch(err) {
            console.log('... next try');
            continue;
        }
    }
    return Promise.reject('no success');
};

getLocation().then(function(result){
    console.log('then:', result);
}).catch(function(reason){
    console.log('error:', reason);
})

嵌套的承诺

承诺内的承诺是可以的。
请注意,使用已解决的承诺来解决承诺的行为“相同” 就像只解决一个承诺一样。无论您解析的是值还是在promise中的已解决promise,等等,您都不会注意到.then()函数的任何区别。

var nestedPromises = new Promise( function( resolve1, reject1 ){
    resolve1( new Promise( function( resolve2, reject2 ){
        resolve2( new Promise( function( resolve3, reject3 ){
            resolve3('resolved value');
        }));
    }));
});

nestedPromises.then( function( value ){
    console.log('value:', value);   // <-- "value: resolved value"
})