我使用以下步骤,在第一次加载页面时完成离线视频,而无需先观看整个视频。
- 注册服务工作器并缓存所有请求。 对于这种情况,静态资源只是
'/'
。如果检查服务工作者的fetch
事件,则会看到随后的请求也被缓存。
- 使用
fetch
API将视频作为blob
请求。
使用fetch请求视频文件并转换成 blob 的示例
const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob());
videoRequest.then(blob => {
...
});
- 使用
IndexedDB
API存储blob
。(使用IndexedDB
而不是LocalStorage
来避免在存储时阻塞主线程。)
就这样!现在,在离线模式下,Service Worker将拦截请求并从缓存中提供html
和blob
。
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Service Worker Test</h1>
<p>Try reloading the page without an Internet connection.</p>
<video controls></video>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(registration => {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(error => {
console.log('ServiceWorker registration failed: ', error);
});
});
} else {
alert('serviceWorker is not in navigator');
}
</script>
<script>
const videos = {
one: document.querySelector('video')
};
const videoRequest = fetch('/path/to/video.mp4').then(response => response.blob());
videoRequest.then(blob => {
const request = indexedDB.open('databaseNameHere', 1);
request.onsuccess = event => {
const db = event.target.result;
const transaction = db.transaction(['videos']);
const objectStore = transaction.objectStore('videos');
const test = objectStore.get('test');
test.onerror = event => {
console.log('error');
};
test.onsuccess = event => {
videos.one.src = window.URL.createObjectURL(test.result.blob);
};
}
request.onupgradeneeded = event => {
const db = event.target.result;
const objectStore = db.createObjectStore('videos', { keyPath: 'name' });
objectStore.transaction.oncomplete = event => {
const videoObjectStore = db.transaction('videos', 'readwrite').objectStore('videos');
videoObjectStore.add({name: 'test', blob: blob});
};
}
});
</script>
</body>
</html>
服务工作者(Service Worker)
const latest = {
cache: 'some-cache-name/v1'
};
self.addEventListener('install', event => {
event.waitUntil(
caches.open(latest.cache).then(cache => {
return cache.addAll([
'/'
]);
})
);
});
self.addEventListener('fetch', event => {
if (event.request.url.startsWith('chrome-extension://')) return;
event.respondWith(
caches.open(latest.cache).then(cache => {
return cache.match(event.request).then(response => {
var fetchPromise = fetch(event.request).then(networkResponse => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
return response || fetchPromise;
})
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.filter(cacheName => {
if (cacheName === latest.cache) {
return false;
}
return true;
}).map(cacheName => {
return caches.delete(cacheName)
})
);
})
);
});
资源:
...一个存储机制,用于缓存请求/响应对象对...
- Umur Karagöz