我正在尝试运行一个获取函数,该函数将从我的服务器获取一些值。但由于某种原因,服务 worker 的注册首先触发,并且它留下未定义的“app_key”导致它抛出异常。 看起来这是一个我不知道如何解决的竞争条件。
我不确定应该如何将值分配给变量以确保它们对其他函数可见。任何建议,将不胜感激。
project_url = window.location.hostname;
var vapi_key;
var app_key;
var pushSub;
var end_point = "https://" + project_url + "/push/subscribe/create";
(() => {
return fetch ("https://" + project_url + "/push/get_public_key"
).then((response) => {
return response.json();
})
.then((responseJSON) => {
vapi_key = responseJSON;
urlBase64ToUint8Array(vapi_key);
console.log("VAPI_KEY: ", vapi_key);
console.log("APP_KEY: ", app_key)
}).catch((err) => {
console.log('Fetch Error : ', err);
});
})();
(() => {
return new Promise((resolve, reject) => {
const permissionResult = Notification.requestPermission((result) => {
resolve(result);
});
if (permissionResult) {
permissionResult.then(resolve, reject);
}
})
.then((permissionResult) => {
if (permissionResult !== 'granted') {
throw new Error('We weren\'t granted permission.');
}
});
})();
(() => {
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register('/sw_bundle.js')
.then((registration) => {
let subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: app_key,
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then((pushSubscription) => {
console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.keys['p256dh'],
auth: pushSubscription.keys['auth']
}
};
sendSubscriptionToBackEnd(subscriptionObject);
return pushSubscription;
});
} else {
console.warn('Push messaging is not supported');
}
})();
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
app_key = outputArray;
}
最佳答案
我不确定您为什么希望它起作用。特别是为什么你使用 IIFE是创造 promise 。无论如何,如果您希望将一个 promise 链接到另一个 promise ,您需要通过在 .then
调用第一个 promise 中创建第二个 promise 来明确这一点。这是一个例子:
const createPromiseA = () => new Promise((resolve) => {
window.setTimeout(() => { console.log('promiseA'); resolve(); }, 2000);
});
const createPromiseB = () => new Promise((resolve) => {
window.setTimeout(() => { console.log('promiseB'); resolve(); }, 3000);
});
createPromiseA().then(createPromiseB);
在您的情况下,您需要执行以下操作:
const fetchKeys = () => fetch ("https://" + project_url + "/push/get_public_key"
).then((response) => {
return response.json();
})
.then((responseJSON) => {
vapi_key = responseJSON;
urlBase64ToUint8Array(vapi_key);
console.log("VAPI_KEY: ", vapi_key);
console.log("APP_KEY: ", app_key)
}).catch((err) => {
console.log('Fetch Error : ', err);
});
const registerWorker = () => {
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register('/sw_bundle.js')
.then((registration) => {
let subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: app_key,
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then((pushSubscription) => {
console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.keys['p256dh'],
auth: pushSubscription.keys['auth']
}
};
sendSubscriptionToBackEnd(subscriptionObject);
return pushSubscription;
});
} else {
return Promise.reject('Push messaging is not supported');
}
};
// …
fetchKeys().then(registerWorker)
.then(() => { console.log('(!) Success!'); });
注意:我认为,使用 IIFE 的更好方法是将整个脚本包装在一个函数中并执行它。这会将变量绑定(bind)到函数的局部范围而不公开它们。 IE。做类似的事情:
(() => {
project_url = window.location.hostname;
var vapi_key;
var app_key;
var pushSub;
var end_point = "https://" + project_url + "/push/subscribe/create";
// ...
const fetchKeys = () => { ... } ;
const registerWorker = () => { ... } ;
// ...
fetchKeys().then(registerWorker)
.then(() => { console.log('(!) Success!'); });
})();
关于javascript - 尝试在注册服务 worker 之前运行获取功能。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52162489/