在异步事件发生时改变 Promise.all() 中 Promise 的 Promise 状态
Change the Promise state of a Promise in Promise.all() when an asynchronous event occurs
我正在使用 google 地图 Api。我有两个异步事件,库 API 调用和页面用户的位置请求。在 geolocate() function
和 getCurrentPosition
中,我检索用户的坐标,此函数 return 如果一切正常,则处于已解决状态的承诺,将位置设置为 value
。为了加载 API 库,我使用 JSONP 并在 loadGoogleAPI()
中动态添加了一个脚本,当库准备就绪时,将调用回调函数 googleAPILoaded
。当上述 2 个异步事件发生并且我在 useGoogleMapsApi() function
(await Promise.all
) 中使用并行执行模式时,我必须继续 'asynchronous execution'。
我的问题是,当我调用 Promise.all
时,googleAPIStatus
的 Promise.all
绑定到其初始值 new Promise(()=>{})
挂起的 Promise。当加载带有 JSONP 的库时,我将变量的值 googleAPIStatus=Promise.resolve()
更改为已解决的 Promise,但 Promise.all
仍然与初始未决 Promise 值相关。
这是代码。我该如何解决?
let googleAPIStatus = new Promise(()=>{});
function googleAPILoaded(){
console.log('loaded');
googleAPIStatus = Promise.resolve();
}
function useGoogleMapsApi(){
loadGoogleAPI();//JSONP with a dynamic script
let [_,posizione]= await Promise.all([googleAPIStatus , geolocate()]); //parallel execution pattern
//Here if resolved either the Promises
}
function loadGoogleAPI(){
let isLibraryLoaded = document.querySelector("script[src='google-api']");
if(!(typeof google === 'object' && typeof google.maps === 'object')){
//Add dynamic script that load the library
let script = document.createElement('script');
script.type='text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places&callback=googleAPILoaded';
script.id = 'google-api';
if(!isLibraryLoaded)
document.body.appendChild(script);
else
isLibraryLoaded.parentNode.replaceChild(script,isLibraryLoaded);
}
}
您可以公开 googleAPIStatus
Promise
的设置,以便您可以在 googleAPILoaded
回调中设置它的状态。
let resolve, reject;
let googleAPIStatus = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
function googleAPILoaded() {
console.log('loaded');
resolve()
}
setTimeout(googleAPILoaded, 100);
googleAPIStatus.then(() => console.log("resolved"))
另一个答案建议公开解析器函数,即“延迟模式”,这是一种由于封装性差而应尽可能避免的反模式。
而是考虑:“如果每个 API 都支持承诺,我将如何编写?”
然后通过包装您在 Promise 构造函数 (which is their primary purpose) 中遇到的每个遗留非承诺 API 来创建该现实,或者更好的是,寻找更新的 APIs。
对于您的情况,已经存在一种更简单的等待脚本加载的方法:
async function loadGoogleAPI() {
if (typeof google === 'object' && typeof google.maps === 'object') {
return;
}
//Add dynamic script that load the library
const script = document.body.appendChild(document.createElement('script'));
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places';
script.id = 'google-api';
await new Promise(resolve => script.onload = resolve);
}
(async () => {
try {
await loadGoogleAPI();
console.log(typeof google.maps);
} catch(e) {
console.log(e);
}
})();
我正在使用 google 地图 Api。我有两个异步事件,库 API 调用和页面用户的位置请求。在 geolocate() function
和 getCurrentPosition
中,我检索用户的坐标,此函数 return 如果一切正常,则处于已解决状态的承诺,将位置设置为 value
。为了加载 API 库,我使用 JSONP 并在 loadGoogleAPI()
中动态添加了一个脚本,当库准备就绪时,将调用回调函数 googleAPILoaded
。当上述 2 个异步事件发生并且我在 useGoogleMapsApi() function
(await Promise.all
) 中使用并行执行模式时,我必须继续 'asynchronous execution'。
我的问题是,当我调用 Promise.all
时,googleAPIStatus
的 Promise.all
绑定到其初始值 new Promise(()=>{})
挂起的 Promise。当加载带有 JSONP 的库时,我将变量的值 googleAPIStatus=Promise.resolve()
更改为已解决的 Promise,但 Promise.all
仍然与初始未决 Promise 值相关。
这是代码。我该如何解决?
let googleAPIStatus = new Promise(()=>{});
function googleAPILoaded(){
console.log('loaded');
googleAPIStatus = Promise.resolve();
}
function useGoogleMapsApi(){
loadGoogleAPI();//JSONP with a dynamic script
let [_,posizione]= await Promise.all([googleAPIStatus , geolocate()]); //parallel execution pattern
//Here if resolved either the Promises
}
function loadGoogleAPI(){
let isLibraryLoaded = document.querySelector("script[src='google-api']");
if(!(typeof google === 'object' && typeof google.maps === 'object')){
//Add dynamic script that load the library
let script = document.createElement('script');
script.type='text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places&callback=googleAPILoaded';
script.id = 'google-api';
if(!isLibraryLoaded)
document.body.appendChild(script);
else
isLibraryLoaded.parentNode.replaceChild(script,isLibraryLoaded);
}
}
您可以公开 googleAPIStatus
Promise
的设置,以便您可以在 googleAPILoaded
回调中设置它的状态。
let resolve, reject;
let googleAPIStatus = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
function googleAPILoaded() {
console.log('loaded');
resolve()
}
setTimeout(googleAPILoaded, 100);
googleAPIStatus.then(() => console.log("resolved"))
另一个答案建议公开解析器函数,即“延迟模式”,这是一种由于封装性差而应尽可能避免的反模式。
而是考虑:“如果每个 API 都支持承诺,我将如何编写?”
然后通过包装您在 Promise 构造函数 (which is their primary purpose) 中遇到的每个遗留非承诺 API 来创建该现实,或者更好的是,寻找更新的 APIs。
对于您的情况,已经存在一种更简单的等待脚本加载的方法:
async function loadGoogleAPI() {
if (typeof google === 'object' && typeof google.maps === 'object') {
return;
}
//Add dynamic script that load the library
const script = document.body.appendChild(document.createElement('script'));
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places';
script.id = 'google-api';
await new Promise(resolve => script.onload = resolve);
}
(async () => {
try {
await loadGoogleAPI();
console.log(typeof google.maps);
} catch(e) {
console.log(e);
}
})();