Github連接weatherPWAjavascript
weatherPWA demo:前端
Web Server
,更改端口便可使用(也能夠本身搭建koa服務器)sync
功能的ServiceWoker監聽器時會抽風,windows親測無此類問題,因此儘可能使用window開發PWA程序!!push Notification
功能時要用到公鑰
和私鑰
,可用Postman進行推送測試var vapidKeys = {
publicKey:"BPwgIYTh9n2u8wpAf-_VzZ4dwaBY8UwfRjWZzcoX6RN7y5xD0RL9U4YDCdeoO3T8nJcWsQdvNirT11xJwPljAyk",
privateKey:"TIrMnK-r--TE7Tnwf-x4JfKwuFKz5tmQuDRWYmuwbhY"
}
function subscribeUserToPush(registration , publicKey){
var subscribeOptions = {
userVisibleOnly : true,
applicationServerKey : window.urlBase64ToUint8Array(publicKey)
};
return registration.pushManager.subscribe(subscribeOptions).then(function(pushSubscription){
console.log('pushscription' ,pushSubscription)
return pushSubscription;
})
}
// base64 => Unit8Array
// https://github.com/web-push-libs/web-push#using-vapid-key-for-applicationserverkey
window.urlBase64ToUint8Array = function (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 (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function sendSubscriptionToServer(body, url) {
url = url || 'http://192.168.1.236:3000/subscription';
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.timeout = 60000;
xhr.onreadystatechange = function () {
var response = {};
if (xhr.readyState === 4 && xhr.status === 200) {
try {
response = JSON.parse(xhr.responseText);
console.log("user subscribed!");
alert("subscribed!");
sub_state = 1;
window.localStorage.setItem("subscription",1);
$('#subscription_btn').remove();
$('#add_btn').remove();
}
catch (e) {
response = xhr.responseText;
}
resolve(response);
}
else if (xhr.readyState === 4) {
resolve();
}
};
xhr.onabort = reject;
xhr.onerror = reject;
xhr.ontimeout = reject;
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(body);
});
}
function PUSH() {
if (sub_state === 0) {
if ('serviceWorker' in navigator && 'PushManager' in window) {
var publicKey = "BPwgIYTh9n2u8wpAf-_VzZ4dwaBY8UwfRjWZzcoX6RN7y5xD0RL9U4YDCdeoO3T8nJcWsQdvNirT11xJwPljAyk";
window.navigator.serviceWorker.ready.then(function (registration) {
//displayNotification();
// open the subscription function of the page
return subscribeUserToPush(registration, publicKey);
}).then(function (subscription) {
var body = {subscription: subscription};
// give every user a unique id in order to push notification
body.uniqueid = new Date().getTime();
console.log('uniqueid', body.uniqueid);
console.log(JSON.stringify(body))
// save the subscription info in the server (bedb used for saving)
return sendSubscriptionToServer(JSON.stringify(body));
}).then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
});
}else{
console.log('Push messaging is not supported.')
}
}else{
alert("you have already subscribed.")
}
}
複製代碼
ServiceWorker
內部沒法使用Localstorage
進行數據儲存,由於ServiceWorker
是異步存儲,因此若是須要將數據從ServiceWorker
傳遞到前端,須要使用IndexedDB
,建立新objectStore
來進行數據通信。在使用indexedDB
是須要注意更新的版本號,若是版本號不變,則沒法添加新的store,也就沒法給數據庫添加新項目,只能更新已有數據。PortForwarding
來將localhost
的網頁推到公網ip上測試,因此在後端的push
端口和sync
端口的ip地址就是當下手機和PC共有網絡的ip地址,並不在localhost
。也就是說在ServiceWorker中對於端口ip地址的調用,必須將ip地址更改,才能正常使用後端端口。ajax
網絡請求,須要使用fetch()
方法來進行網絡請求fetch('http://192.168.1.137:3000/sync').then(function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: '+response.status);
return;
}
response.text().then(function (data) {
console.log("succeed access to sync interface");
var request = indexedDB.open("weatherPWA");
request.onupgradeneeded = function (event) {
var store = event.target.result.createObjectStore("real time", {keyPath:'id',autoIncrement: true });
store.createIndex('time','time',{unique:false});
}
request.onsuccess = function (event) {
console.log(data);
db = this.result;
var tx = db.transaction("real time",'readwrite');
store = tx.objectStore("real time");
var obj = {
id:0,
time:data
}
var req = store.put(obj);
req.onsuccess = function (event) {
//console.log(obj+" insert in DB successful");
};
req.onerror = function (event) {
console.log(obj+" insert in DB error",this.error);
}
}
request.onerror = function (event) {
console.log("opendb:", event);
};
console.log(data);
})
})
複製代碼