[英]JS promise inside promise
应该在 3 次尝试中检索位置的getLocation()
函数返回undefined
。 navigator.geolocation.getCurrentPosition()
返回正确的位置,但问题在于承诺处理。
问题显然是我在承诺中调用了一个承诺。 我不允许在已经声明为async
geolocate()
使用await
关键字。
原始调用:
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()
:
async geolocate() {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
(position) => {
resolve(position);
},
(err) => {
reject(err);
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
);
});
}
只要以下内容在声明为 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);
}
如果没有async
关键字,就不能在函数内部使用await
。 所以发生错误是因为 executor 函数不是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 executor 成为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;
};
因此,理论上,您可以通过以下方式解决您的问题(尽管可能有更好的方法。对于异步函数中的“拒绝”,另请参阅如何在 async/await 语法中拒绝? )。
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);
})
承诺里面的承诺是可以的。
请注意,使用已解决的承诺解决承诺与仅解决一个承诺的行为“相同” 。 您不会注意到.then()
函数有任何区别,无论您是解析一个值,还是在 Promise 中解析一个 promise,...等等。
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"
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.