Service Workers এর মাধ্যমে, আমরা ডেভেলপারদের নেটওয়ার্ক সংযোগ সমাধানের একটি উপায় দিয়েছি। আপনি ক্যাশিং এবং অনুরোধগুলি কীভাবে পরিচালনা করা হয় তার উপর নিয়ন্ত্রণ পাবেন। এর অর্থ হল আপনি আপনার নিজস্ব প্যাটার্ন তৈরি করতে পারবেন। বিচ্ছিন্নভাবে কয়েকটি সম্ভাব্য প্যাটার্ন দেখুন, তবে বাস্তবে, আপনি সম্ভবত URL এবং প্রসঙ্গের উপর নির্ভর করে সেগুলি একসাথে ব্যবহার করবেন।
এই ধরণের কিছু প্যাটার্নের একটি কার্যকরী ডেমোর জন্য, Trained-to-trill দেখুন।
কখন সম্পদ সংরক্ষণ করতে হবে
পরিষেবা কর্মীরা আপনাকে ক্যাশিং থেকে স্বাধীনভাবে অনুরোধগুলি পরিচালনা করতে দেয়, তাই আমি সেগুলি আলাদাভাবে প্রদর্শন করব। প্রথমে, কখন ক্যাশ ব্যবহার করা উচিত তা নির্ধারণ করা।
ইনস্টলেশনের সময়, নির্ভরতা হিসেবে

সার্ভিস ওয়ার্কার এপিআই আপনাকে একটি install ইভেন্ট দেয়। আপনি এটি ব্যবহার করে জিনিসপত্র প্রস্তুত করতে পারেন, এমন জিনিসপত্র যা অন্যান্য ইভেন্ট পরিচালনা করার আগে প্রস্তুত থাকতে হবে। install সময়, আপনার সার্ভিস ওয়ার্কারের পূর্ববর্তী সংস্করণগুলি চলতে থাকে এবং পৃষ্ঠাগুলি পরিবেশন করতে থাকে। এই সময়ে আপনি যা-ই করুন না কেন, বিদ্যমান সার্ভিস ওয়ার্কারকে ব্যাহত করা উচিত নয়।
এর জন্য আদর্শ : CSS, ছবি, ফন্ট, JS, টেমপ্লেট, অথবা আপনার সাইটের সেই সংস্করণের জন্য স্ট্যাটিক বলে মনে হয় এমন অন্য যেকোনো কিছু।
যেসব জিনিস আপনার সাইটে আনতে ব্যর্থ হলে তা সম্পূর্ণরূপে অকার্যকর করে তুলবে, সেই জিনিসগুলি আনুন, যেগুলি একটি সমতুল্য প্ল্যাটফর্ম-নির্দিষ্ট অ্যাপ প্রাথমিক ডাউনলোডের অংশ করবে।
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open('mysite-static-v3').then(function (cache) {
return cache.addAll([
'/css/whatever-v3.css',
'/css/imgs/sprites-v6.png',
'/css/fonts/whatever-v8.woff',
'/js/all-min-v4.js',
// etc.
]);
}),
);
});
event.waitUntil ইনস্টলেশনের দৈর্ঘ্য এবং সাফল্য নির্ধারণের জন্য একটি প্রতিশ্রুতি নেয়। যদি প্রতিশ্রুতি প্রত্যাখ্যান করা হয়, তাহলে ইনস্টলেশনটি ব্যর্থ বলে বিবেচিত হবে এবং এই Service Workerটি পরিত্যক্ত হবে (যদি একটি পুরানো সংস্করণ চলমান থাকে, তবে এটি অক্ষত থাকবে)। caches.open() এবং cache.addAll() প্রতিশ্রুতি ফেরত দেয়। যদি কোনও সংস্থান আনা ব্যর্থ হয়, তাহলে cache.addAll() কল প্রত্যাখ্যান করে।
প্রশিক্ষিত-থেকে-থ্রিলে আমি স্ট্যাটিক অ্যাসেট ক্যাশে করার জন্য এটি ব্যবহার করি।
ইনস্টলেশনের সময়, নির্ভরতা হিসেবে নয়

এটি নির্ভরতা হিসেবে ইনস্টল করার মতোই, কিন্তু ইনস্টল সম্পূর্ণ হতে বিলম্ব করবে না এবং ক্যাশিং ব্যর্থ হলে ইনস্টলেশন ব্যর্থ হবে না।
এর জন্য আদর্শ : বৃহত্তর সম্পদ যা সরাসরি প্রয়োজন হয় না, যেমন খেলার পরবর্তী স্তরের জন্য সম্পদ।
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open('mygame-core-v1').then(function (cache) {
cache
.addAll
// levels 11-20
();
return cache
.addAll
// core assets and levels 1-10
();
}),
);
});
এই উদাহরণটি cache.addAll লেভেল ১১-২০ এর জন্য event.waitUntil তে ফেরত যাওয়ার প্রতিশ্রুতি দেয় না, তাই এটি ব্যর্থ হলেও, গেমটি অফলাইনে উপলব্ধ থাকবে। অবশ্যই, আপনাকে সেই লেভেলগুলির সম্ভাব্য অনুপস্থিতি পূরণ করতে হবে এবং যদি সেগুলি অনুপস্থিত থাকে তবে সেগুলি পুনরায় ক্যাশে করার চেষ্টা করতে হবে।
১১-২০ লেভেলের ডাউনলোডের সময় পরিষেবা কর্মী নিহত হতে পারে কারণ এটি ইভেন্ট পরিচালনা শেষ করে ফেলেছে, অর্থাৎ সেগুলি ক্যাশে করা হবে না। ওয়েব পিরিওডিক ব্যাকগ্রাউন্ড সিঙ্ক্রোনাইজেশন API এই ধরণের কেস এবং সিনেমার মতো বৃহত্তর ডাউনলোড পরিচালনা করতে পারে।
সক্রিয় করার সময়

এর জন্য আদর্শ : পরিষ্কার-পরিচ্ছন্নতা এবং স্থানান্তর।
একবার নতুন সার্ভিস ওয়ার্কার ইনস্টল হয়ে গেলে এবং পূর্ববর্তী সংস্করণটি ব্যবহার না করা হলে, নতুনটি সক্রিয় হয় এবং আপনি একটি activate ইভেন্ট পান। যেহেতু পূর্ববর্তী সংস্করণটি অপ্রচলিত, তাই IndexedDB-তে স্কিমা মাইগ্রেশন পরিচালনা করার এবং অব্যবহৃত ক্যাশে মুছে ফেলার জন্য এটি একটি ভাল সময়।
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames
.filter(function (cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
})
.map(function (cacheName) {
return caches.delete(cacheName);
}),
);
}),
);
});
অ্যাক্টিভেশনের সময়, fetch মতো ইভেন্টগুলিকে একটি সারিতে রাখা হয়, তাই দীর্ঘ অ্যাক্টিভেশন পৃষ্ঠা লোড ব্লক করতে পারে। আপনার অ্যাক্টিভেশন যতটা সম্ভব সহজ রাখুন এবং এটি কেবল সেই জিনিসগুলির জন্য ব্যবহার করুন যা আপনি পূর্ববর্তী সংস্করণটি সক্রিয় থাকাকালীন করতে পারেননি ।
trained-to-thrill- এ আমি পুরানো ক্যাশে মুছে ফেলার জন্য এটি ব্যবহার করি।
ব্যবহারকারীর মিথস্ক্রিয়া সম্পর্কে

এর জন্য আদর্শ : যখন পুরো সাইটটি অফলাইনে নেওয়া যায় না, এবং আপনি ব্যবহারকারীকে তাদের পছন্দের কন্টেন্ট অফলাইনে দেখতে দেওয়ার অনুমতি দিয়েছেন। যেমন YouTube-এর মতো কোনও ভিডিও, Wikipedia-এর কোনও নিবন্ধ, Flickr-এর কোনও নির্দিষ্ট গ্যালারি।
ব্যবহারকারীকে "পরে পড়ুন" অথবা "অফলাইনের জন্য সংরক্ষণ করুন" বোতামটি দিন। এটি ক্লিক করা হলে, নেটওয়ার্ক থেকে আপনার যা প্রয়োজন তা আনুন এবং ক্যাশে পপ করুন।
document.querySelector('.cache-article').addEventListener('click', function (event) {
event.preventDefault();
var id = this.dataset.articleId;
caches.open('mysite-article-' + id).then(function (cache) {
fetch('/get-article-urls?id=' + id)
.then(function (response) {
// /get-article-urls returns a JSON-encoded array of
// resource URLs that a given article depends on
return response.json();
})
.then(function (urls) {
cache.addAll(urls);
});
});
});
ক্যাশে এপিআই পৃষ্ঠা এবং পরিষেবা কর্মীদের কাছ থেকে পাওয়া যায়, যার অর্থ আপনি পৃষ্ঠা থেকে সরাসরি ক্যাশে যোগ করতে পারেন।
নেটওয়ার্ক প্রতিক্রিয়া

এর জন্য আদর্শ : ব্যবহারকারীর ইনবক্স বা নিবন্ধের বিষয়বস্তুর মতো রিসোর্স ঘন ঘন আপডেট করা। অবতারের মতো অপ্রয়োজনীয় বিষয়বস্তুর জন্যও কার্যকর, তবে যত্ন নেওয়া প্রয়োজন।
যদি কোনও অনুরোধ ক্যাশে থাকা কোনও কিছুর সাথে মেলে না, তাহলে নেটওয়ার্ক থেকে এটি পান, পৃষ্ঠায় পাঠান এবং একই সাথে ক্যাশে যুক্ত করুন।
যদি আপনি এটি বিভিন্ন ধরণের URL-এর জন্য করেন, যেমন avatars, তাহলে আপনার অরিজিনের স্টোরেজ যাতে ফুলে না যায় সেদিকে আপনাকে সতর্ক থাকতে হবে। যদি ব্যবহারকারীর ডিস্কের স্থান পুনরুদ্ধার করতে হয় তবে আপনি প্রধান প্রার্থী হতে চান না। নিশ্চিত করুন যে আপনি ক্যাশে থাকা আইটেমগুলি সরিয়ে ফেলছেন যা আপনার আর প্রয়োজন নেই।
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open('mysite-dynamic').then(function (cache) {
return cache.match(event.request).then(function (response) {
return (
response ||
fetch(event.request).then(function (response) {
cache.put(event.request, response.clone());
return response;
})
);
});
}),
);
});
মেমোরির কার্যকর ব্যবহারের জন্য, আপনি শুধুমাত্র একবারই একটি প্রতিক্রিয়া/অনুরোধের মূল অংশ পড়তে পারবেন। কোড নমুনাটি .clone() ব্যবহার করে অতিরিক্ত কপি তৈরি করে যা আলাদাভাবে পড়া যায়।
প্রশিক্ষিত-থেকে-থ্রিলে আমি Flickr ছবি ক্যাশে করার জন্য এটি ব্যবহার করি।
স্টেল-ওয়াইল্ড-রিভ্যালিডেট

আদর্শ : ঘন ঘন রিসোর্স আপডেট করা যেখানে সর্বশেষ সংস্করণ থাকা অপরিহার্য নয়। অবতার এই বিভাগে পড়তে পারে।
যদি কোনও ক্যাশে ভার্সন পাওয়া যায়, তাহলে এটি ব্যবহার করুন, কিন্তু পরের বারের জন্য একটি আপডেট আনুন।
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open('mysite-dynamic').then(function (cache) {
return cache.match(event.request).then(function (response) {
var fetchPromise = fetch(event.request).then(function (networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return response || fetchPromise;
});
}),
);
});
এটি HTTP এর stale-while-revalidate এর মতোই।
পুশ বার্তায়

Push API হল সার্ভিস ওয়ার্কারের উপরে তৈরি আরেকটি বৈশিষ্ট্য। এটি OS এর মেসেজিং সার্ভিস থেকে আসা বার্তার প্রতিক্রিয়ায় সার্ভিস ওয়ার্কারকে জাগিয়ে তুলতে সাহায্য করে। ব্যবহারকারীর সাইটে কোনও ট্যাব খোলা না থাকলেও এটি ঘটে। শুধুমাত্র সার্ভিস ওয়ার্কারকে জাগিয়ে তোলা হয়। আপনি একটি পৃষ্ঠা থেকে এটি করার জন্য অনুমতি চান এবং ব্যবহারকারীকে অনুরোধ করা হয়।
এর জন্য আদর্শ : কোনও বিজ্ঞপ্তি সম্পর্কিত সামগ্রী, যেমন চ্যাট বার্তা, কোনও ব্রেকিং নিউজ স্টোরি, বা কোনও ইমেল। এছাড়াও কদাচিৎ এমন সামগ্রী পরিবর্তন করা যা তাৎক্ষণিক সিঙ্ক থেকে উপকৃত হয়, যেমন করণীয় তালিকা আপডেট বা ক্যালেন্ডার পরিবর্তন।
সাধারণ চূড়ান্ত ফলাফল হল একটি বিজ্ঞপ্তি যা ট্যাপ করলে, একটি প্রাসঙ্গিক পৃষ্ঠা খোলে এবং ফোকাস করে, এবং যার জন্য আগে থেকে ক্যাশে আপডেট করা অত্যন্ত গুরুত্বপূর্ণ। পুশ বার্তা পাওয়ার সময় ব্যবহারকারী অনলাইনে থাকেন, কিন্তু বিজ্ঞপ্তির সাথে যোগাযোগ করার সময় তারা নাও থাকতে পারেন, তাই এই সামগ্রীটি অফলাইনে উপলব্ধ করা অত্যন্ত গুরুত্বপূর্ণ।
এই কোডটি বিজ্ঞপ্তি দেখানোর আগে ক্যাশে আপডেট করে:
self.addEventListener('push', function (event) {
if (event.data.text() == 'new-email') {
event.waitUntil(
caches
.open('mysite-dynamic')
.then(function (cache) {
return fetch('/inbox.json').then(function (response) {
cache.put('/inbox.json', response.clone());
return response.json();
});
})
.then(function (emails) {
registration.showNotification('New email', {
body: 'From ' + emails[0].from.name,
tag: 'new-email',
});
}),
);
}
});
self.addEventListener('notificationclick', function (event) {
if (event.notification.tag == 'new-email') {
// Assume that all of the resources needed to render
// /inbox/ have previously been cached, e.g. as part
// of the install handler.
new WindowClient('/inbox/');
}
});
ব্যাকগ্রাউন্ড-সিঙ্কে

ব্যাকগ্রাউন্ড সিঙ্ক হল সার্ভিস ওয়ার্কারের উপরে তৈরি আরেকটি বৈশিষ্ট্য। এটি আপনাকে একবারের জন্য অথবা (অত্যন্ত হিউরিস্টিক) ব্যবধানে ব্যাকগ্রাউন্ড ডেটা সিঙ্ক্রোনাইজেশনের অনুরোধ করতে দেয়। ব্যবহারকারীর আপনার সাইটে কোনও ট্যাব খোলা না থাকলেও এটি ঘটে। শুধুমাত্র সার্ভিস ওয়ার্কারকে জাগিয়ে তোলা হয়। আপনি একটি পৃষ্ঠা থেকে এটি করার জন্য অনুমতি চান এবং ব্যবহারকারীকে অনুরোধ করা হয়।
এর জন্য আদর্শ : অ-জরুরি আপডেট, বিশেষ করে যেগুলি এত নিয়মিত হয় যে ব্যবহারকারীদের জন্য প্রতি আপডেটে একটি পুশ বার্তা খুব ঘন ঘন আসে, যেমন সোশ্যাল টাইমলাইন বা সংবাদ নিবন্ধ।
self.addEventListener('sync', function (event) {
if (event.id == 'update-leaderboard') {
event.waitUntil(
caches.open('mygame-dynamic').then(function (cache) {
return cache.add('/leaderboard.json');
}),
);
}
});
ক্যাশে স্থায়িত্ব
আপনার origin-কে একটি নির্দিষ্ট পরিমাণ খালি জায়গা দেওয়া হয়েছে যাতে আপনি যা চান তা করতে পারেন। এই খালি জায়গাটি সমস্ত origin স্টোরেজের মধ্যে ভাগ করা হয়: (স্থানীয়) Storage , IndexedDB , File System Access , এবং অবশ্যই Caches ।
আপনি কত টাকা পাবেন তা নির্দিষ্ট করা নেই। ডিভাইস এবং স্টোরেজের অবস্থার উপর নির্ভর করে এটি ভিন্ন হয়। আপনার কাছে কত টাকা আছে তা আপনি জানতে পারবেন:
if (navigator.storage && navigator.storage.estimate) {
const quota = await navigator.storage.estimate();
// quota.usage -> Number of bytes used.
// quota.quota -> Maximum number of bytes available.
const percentageUsed = (quota.usage / quota.quota) * 100;
console.log(`You've used ${percentageUsed}% of the available storage.`);
const remaining = quota.quota - quota.usage;
console.log(`You can write up to ${remaining} more bytes.`);
}
তবে, অন্যান্য ব্রাউজার স্টোরেজের মতো, ডিভাইসটি স্টোরেজের চাপে পড়লে ব্রাউজার আপনার ডেটা ফেলে দিতে পারে। দুর্ভাগ্যবশত, ব্রাউজারটি যেকোনো মূল্যে আপনি যে সিনেমাগুলি রাখতে চান এবং যে গেমটি সম্পর্কে আপনি সত্যিই চিন্তিত নন তার মধ্যে পার্থক্য বলতে পারে না।
এই সমস্যা সমাধানের জন্য, StorageManager ইন্টারফেসটি ব্যবহার করুন:
// From a page:
navigator.storage.persist()
.then(function(persisted) {
if (persisted) {
// Hurrah, your data is here to stay!
} else {
// So sad, your data may get chucked. Sorry.
});
অবশ্যই, ব্যবহারকারীকে অনুমতি দিতে হবে। এর জন্য, Permissions API ব্যবহার করুন।
এই প্রবাহের ব্যবহারকারীকে অংশ হিসেবে অন্তর্ভুক্ত করা গুরুত্বপূর্ণ, কারণ আমরা এখন আশা করতে পারি যে তারা মুছে ফেলার নিয়ন্ত্রণ পাবে। যদি তাদের ডিভাইসে স্টোরেজের চাপ পড়ে এবং অপ্রয়োজনীয় ডেটা সাফ করেও সমস্যার সমাধান না হয়, তাহলে ব্যবহারকারী সিদ্ধান্ত নিতে পারবেন কোন আইটেমগুলি রাখবেন এবং কোনগুলি সরিয়ে ফেলবেন।
এটি কাজ করার জন্য, অপারেটিং সিস্টেমগুলিকে ব্রাউজারটিকে একক আইটেম হিসাবে রিপোর্ট করার পরিবর্তে, স্টোরেজ ব্যবহারের ভাঙ্গনের ক্ষেত্রে "টেকসই" উত্সগুলিকে প্ল্যাটফর্ম-নির্দিষ্ট অ্যাপগুলির সমতুল্য হিসাবে বিবেচনা করতে হবে।
পরিবেশনের পরামর্শ
আপনি কত ক্যাশিং করেন তা বিবেচ্য নয়, পরিষেবা কর্মী কেবল তখনই ক্যাশ ব্যবহার করেন যখন আপনি কখন এবং কীভাবে তা বলবেন। অনুরোধগুলি পরিচালনা করার জন্য এখানে কয়েকটি প্যাটার্ন রয়েছে:
শুধুমাত্র ক্যাশে

আপনার সাইটের একটি নির্দিষ্ট "সংস্করণ"-এর জন্য স্ট্যাটিক বলে মনে হয় এমন যেকোনো কিছুর জন্য আদর্শ । আপনার ইনস্টল ইভেন্টে এগুলি ক্যাশে করা উচিত ছিল, যাতে আপনি তাদের সেখানে থাকার উপর নির্ভর করতে পারেন।
self.addEventListener('fetch', function (event) {
// If a match isn't found in the cache, the response
// will look like a connection error
event.respondWith(caches.match(event.request));
});
…যদিও আপনাকে প্রায়শই এই কেসটি বিশেষভাবে পরিচালনা করতে হয় না, ক্যাশে, নেটওয়ার্কে ফিরে আসা এটিকে কভার করে।
শুধুমাত্র নেটওয়ার্ক

আদর্শ : যেসব জিনিসের অফলাইন সমতুল্য নেই, যেমন অ্যানালিটিক্স পিং, নন-জিইটি অনুরোধ।
self.addEventListener('fetch', function (event) {
event.respondWith(fetch(event.request));
// or don't call event.respondWith, which
// will result in default browser behavior
});
…যদিও আপনাকে প্রায়শই এই কেসটি বিশেষভাবে পরিচালনা করতে হয় না, ক্যাশে, নেটওয়ার্কে ফিরে আসা এটিকে কভার করে।
ক্যাশে, নেটওয়ার্কে ফিরে আসছে

এর জন্য আদর্শ : প্রথমে অফলাইন তৈরি করা। এই ধরনের ক্ষেত্রে, আপনি বেশিরভাগ অনুরোধ এইভাবে পরিচালনা করবেন। অন্যান্য প্যাটার্নগুলি আগত অনুরোধের উপর ভিত্তি করে ব্যতিক্রম।
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
}),
);
});
এটি আপনাকে ক্যাশে থাকা জিনিসগুলির জন্য "শুধুমাত্র ক্যাশে" আচরণ এবং ক্যাশে না থাকা যেকোনো কিছুর জন্য "শুধুমাত্র নেটওয়ার্ক" আচরণ দেয় (যার মধ্যে সমস্ত নন-GET অনুরোধ অন্তর্ভুক্ত, কারণ সেগুলি ক্যাশে করা যায় না)।
ক্যাশে এবং নেটওয়ার্ক প্রতিযোগিতা

এর জন্য আদর্শ : ছোট সম্পদ যেখানে আপনি ধীর ডিস্ক অ্যাক্সেস সহ ডিভাইসগুলিতে কর্মক্ষমতা খুঁজছেন।
পুরনো হার্ড ড্রাইভ, ভাইরাস স্ক্যানার এবং দ্রুত ইন্টারনেট সংযোগের কিছু সংমিশ্রণ ব্যবহার করে, নেটওয়ার্ক থেকে রিসোর্স পাওয়া ডিস্কে যাওয়ার চেয়ে দ্রুত হতে পারে। তবে, ব্যবহারকারীর ডিভাইসে কন্টেন্ট থাকা অবস্থায় নেটওয়ার্কে যাওয়া ডেটার অপচয় হতে পারে, তাই মনে রাখবেন।
// Promise.race rejects when a promise rejects before fulfilling.
// To make a race function:
function promiseAny(promises) {
return new Promise((resolve, reject) => {
// make sure promises are all promises
promises = promises.map((p) => Promise.resolve(p));
// resolve this promise as soon as one resolves
promises.forEach((p) => p.then(resolve));
// reject if all promises reject
promises.reduce((a, b) => a.catch(() => b)).catch(() => reject(Error('All failed')));
});
}
self.addEventListener('fetch', function (event) {
event.respondWith(promiseAny([caches.match(event.request), fetch(event.request)]));
});
নেটওয়ার্ক আবার ক্যাশে ফিরে আসছে

এর জন্য আদর্শ : সাইটের "সংস্করণ" এর বাইরে ঘন ঘন আপডেট হওয়া রিসোর্সের দ্রুত সমাধান। যেমন নিবন্ধ, অবতার, সোশ্যাল মিডিয়া টাইমলাইন এবং গেম লিডারবোর্ড।
এর অর্থ হল আপনি অনলাইন ব্যবহারকারীদের সবচেয়ে আপ-টু-ডেট কন্টেন্ট দেবেন, কিন্তু অফলাইন ব্যবহারকারীরা একটি পুরানো ক্যাশেড ভার্সন পাবেন। যদি নেটওয়ার্ক অনুরোধ সফল হয় তবে আপনি সম্ভবত ক্যাশ এন্ট্রি আপডেট করতে চাইবেন।
তবে, এই পদ্ধতিতে কিছু ত্রুটি রয়েছে। যদি ব্যবহারকারীর সংযোগ বিচ্ছিন্ন বা ধীর হয়, তাহলে তাদের ডিভাইসে সম্পূর্ণ গ্রহণযোগ্য কন্টেন্ট পাওয়ার জন্য নেটওয়ার্ক ব্যর্থ হওয়ার জন্য অপেক্ষা করতে হবে। এটি অত্যন্ত দীর্ঘ সময় নিতে পারে এবং ব্যবহারকারীর অভিজ্ঞতাকে হতাশাজনক করে তোলে। আরও ভালো সমাধানের জন্য পরবর্তী প্যাটার্ন, Cache তারপর network দেখুন।
self.addEventListener('fetch', function (event) {
event.respondWith(
fetch(event.request).catch(function () {
return caches.match(event.request);
}),
);
});
ক্যাশে তারপর নেটওয়ার্ক

এর জন্য আদর্শ : ঘন ঘন আপডেট হওয়া কন্টেন্ট। যেমন নিবন্ধ, সোশ্যাল মিডিয়া টাইমলাইন এবং গেম। লিডারবোর্ড।
এর জন্য পৃষ্ঠাটিকে দুটি অনুরোধ করতে হবে, একটি ক্যাশে এবং একটি নেটওয়ার্কে। ধারণাটি হল প্রথমে ক্যাশে করা ডেটা দেখানো, তারপর নেটওয়ার্ক ডেটা আসার সময় পৃষ্ঠাটি আপডেট করা।
কখনও কখনও নতুন ডেটা (যেমন গেম লিডারবোর্ড) এলে আপনি কেবল বর্তমান ডেটা প্রতিস্থাপন করতে পারেন, তবে এটি বৃহত্তর সামগ্রীর সাথে বিঘ্নিত হতে পারে। মূলত, ব্যবহারকারী যা পড়ছেন বা ইন্টারঅ্যাক্ট করছেন তা "অদৃশ্য" করবেন না।
টুইটার পুরাতন কন্টেন্টের উপরে নতুন কন্টেন্ট যোগ করে এবং স্ক্রোল পজিশন সামঞ্জস্য করে যাতে ব্যবহারকারী নিরবচ্ছিন্নভাবে কাজ করতে পারেন। এটি সম্ভব কারণ টুইটার কন্টেন্টের জন্য বেশিরভাগ ক্ষেত্রেই রৈখিক ক্রম বজায় রাখে। আমি এই প্যাটার্নটি প্রশিক্ষিত-থেকে-থ্রিলের জন্য অনুলিপি করেছি যাতে কন্টেন্ট যত তাড়াতাড়ি সম্ভব স্ক্রিনে পাওয়া যায়, এবং আপ-টু-ডেট কন্টেন্ট আসার সাথে সাথে তা প্রদর্শন করা যায়।
পৃষ্ঠায় কোড :
var networkDataReceived = false;
startSpinner();
// fetch fresh data
var networkUpdate = fetch('/data.json')
.then(function (response) {
return response.json();
})
.then(function (data) {
networkDataReceived = true;
updatePage(data);
});
// fetch cached data
caches
.match('/data.json')
.then(function (response) {
if (!response) throw Error('No data');
return response.json();
})
.then(function (data) {
// don't overwrite newer network data
if (!networkDataReceived) {
updatePage(data);
}
})
.catch(function () {
// we didn't get cached data, the network is our last hope:
return networkUpdate;
})
.catch(showErrorMessage)
.then(stopSpinner);
পরিষেবা কর্মীর কোড :
আপনার সর্বদা নেটওয়ার্কে যাওয়া উচিত এবং যাওয়ার সময় একটি ক্যাশে আপডেট করা উচিত।
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open('mysite-dynamic').then(function (cache) {
return fetch(event.request).then(function (response) {
cache.put(event.request, response.clone());
return response;
});
}),
);
});
trained-to-thrill- এ আমি fetch-এর পরিবর্তে XHR ব্যবহার করে এবং Accept হেডারের অপব্যবহার করে পরিষেবা কর্মীকে ফলাফল কোথা থেকে পেতে হবে তা জানিয়েছিলাম ( পৃষ্ঠা কোড , পরিষেবা কর্মী কোড )।
জেনেরিক ফলব্যাক

যদি আপনি ক্যাশে বা নেটওয়ার্ক থেকে কিছু পরিবেশন করতে ব্যর্থ হন, তাহলে একটি জেনেরিক ফলব্যাক প্রদান করুন।
এর জন্য আদর্শ : অবতার, ব্যর্থ POST অনুরোধ এবং "অফলাইনে থাকাকালীন অনুপলব্ধ" পৃষ্ঠার মতো গৌণ চিত্রাবলী।
self.addEventListener('fetch', function (event) {
event.respondWith(
// Try the cache
caches
.match(event.request)
.then(function (response) {
// Fall back to network
return response || fetch(event.request);
})
.catch(function () {
// If both fail, show a generic fallback:
return caches.match('/offline.html');
// However, in reality you'd have many different
// fallbacks, depending on URL and headers.
// Eg, a fallback silhouette image for avatars.
}),
);
});
আপনি যে আইটেমটিতে ফিরে যাবেন সেটি সম্ভবত একটি ইনস্টল নির্ভরতা ।
যদি আপনার পৃষ্ঠাটি কোনও ইমেল পোস্ট করে, তাহলে আপনার পরিষেবা কর্মী ইমেলটি একটি IndexedDB আউটবক্সে সংরক্ষণ করতে পারেন এবং পৃষ্ঠাটিকে বলতে পারেন যে প্রেরণ ব্যর্থ হয়েছে কিন্তু ডেটা সফলভাবে ধরে রাখা হয়েছে।
সার্ভিস ওয়ার্কার-সাইড টেমপ্লেটিং

আদর্শ : যেসব পৃষ্ঠার সার্ভার প্রতিক্রিয়া ক্যাশে করা যাবে না।
সার্ভারে পৃষ্ঠাগুলি রেন্ডার করা দ্রুততর , কিন্তু এর অর্থ হতে পারে এমন স্টেট ডেটা অন্তর্ভুক্ত করা যা ক্যাশে অর্থহীন হতে পারে, যেমন সাইন-ইন অবস্থা। যদি আপনার পৃষ্ঠাটি কোনও পরিষেবা কর্মী দ্বারা নিয়ন্ত্রিত হয়, তাহলে আপনি একটি টেমপ্লেট সহ JSON ডেটা অনুরোধ করতে পারেন এবং পরিবর্তে তা রেন্ডার করতে পারেন।
importScripts('templating-engine.js');
self.addEventListener('fetch', function (event) {
var requestURL = new URL(event.request.url);
event.respondWith(
Promise.all([
caches.match('/article-template.html').then(function (response) {
return response.text();
}),
caches.match(requestURL.path + '.json').then(function (response) {
return response.json();
}),
]).then(function (responses) {
var template = responses[0];
var data = responses[1];
return new Response(renderTemplate(template, data), {
headers: {
'Content-Type': 'text/html',
},
});
}),
);
});
একসাথে রাখো।
আপনি এই পদ্ধতিগুলির মধ্যে একটিতে সীমাবদ্ধ নন। আসলে, অনুরোধের URL এর উপর নির্ভর করে আপনি সম্ভবত এগুলি অনেকগুলি ব্যবহার করবেন। উদাহরণস্বরূপ, প্রশিক্ষিত-থেকে-রোমাঞ্চকর ব্যবহার:
- স্ট্যাটিক UI এবং আচরণের জন্য ইনস্টলে ক্যাশে
- ফ্লিকার ছবি এবং ডেটার জন্য নেটওয়ার্ক প্রতিক্রিয়াতে ক্যাশে
- বেশিরভাগ অনুরোধের জন্য , ক্যাশে থেকে আনুন, নেটওয়ার্কে ফিরে যান
- Flickr অনুসন্ধান ফলাফলের জন্য ক্যাশে থেকে আনুন, তারপর নেটওয়ার্ক থেকে ।
অনুরোধটি দেখুন এবং কী করবেন তা সিদ্ধান্ত নিন:
self.addEventListener('fetch', function (event) {
// Parse the URL:
var requestURL = new URL(event.request.url);
// Handle requests to a particular host specifically
if (requestURL.hostname == 'api.example.com') {
event.respondWith(/* some combination of patterns */);
return;
}
// Routing for local URLs
if (requestURL.origin == location.origin) {
// Handle article URLs
if (/^\/article\//.test(requestURL.pathname)) {
event.respondWith(/* some other combination of patterns */);
return;
}
if (/\.webp$/.test(requestURL.pathname)) {
event.respondWith(/* some other combination of patterns */);
return;
}
if (request.method == 'POST') {
event.respondWith(/* some other combination of patterns */);
return;
}
if (/cheese/.test(requestURL.pathname)) {
event.respondWith(
new Response('Flagrant cheese error', {
status: 512,
}),
);
return;
}
}
// A sensible default pattern
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
}),
);
});
আরও পড়া
- পরিষেবা কর্মী এবং ক্যাশে স্টোরেজ API
- জাভাস্ক্রিপ্ট প্রতিশ্রুতি—একটি ভূমিকা : প্রতিশ্রুতির নির্দেশিকা
ক্রেডিট
সুন্দর আইকনগুলির জন্য:
- buzzyrobot দ্বারা কোড
- স্কট লুইসের ক্যালেন্ডার
- বেন রিজোর নেটওয়ার্ক
- থমাস লে বাসের এসডি
- iconsmind.com এর সিপিইউ
- ট্র্যাসনিকের ট্র্যাশ
- @daosme এর বিজ্ঞপ্তি
- মিস্টার পিক্সেল দ্বারা লেআউট
- পিজে ওনোরির ক্লাউড
আর "প্রকাশ" করার আগে অনেক ভুল ধরার জন্য জেফ পসনিককে ধন্যবাদ।