JavaScript Modul Workerlari yordamida fon jarayonlarini optimallashtirib, global auditoriya uchun veb-ilovalar ishlashini va foydalanuvchi tajribasini oshiring.
JavaScript Modul Workerlar: Global Raqamli Dunyo uchun Fon Jarayonlari Shakllarini O'zlashtirish
Bugungi o'zaro bog'langan dunyoda veb-ilovalar foydalanuvchining joylashuvi yoki qurilmasining imkoniyatlaridan qat'i nazar, uzluksiz, sezgir va samarali tajribani taqdim etishi kutilmoqda. Bunga erishishdagi muhim qiyinchiliklardan biri bu asosiy foydalanuvchi interfeysini muzlatib qo'ymasdan, hisoblash jihatidan og'ir vazifalarni boshqarishdir. Aynan shu yerda JavaScript-ning Web Workerlari yordamga keladi. Aniqroq aytganda, JavaScript Modul Workerlarining paydo bo'lishi fon jarayonlariga bo'lgan yondashuvimizni inqilob qildi, bu vazifalarni yengillashtirishning yanada mustahkam va modulli usulini taklif etdi.
Ushbu keng qamrovli qo'llanma JavaScript Modul Workerlarining kuchini o'rganadi, veb-ilovangizning samaradorligi va foydalanuvchi tajribasini sezilarli darajada oshirishi mumkin bo'lgan turli xil fon jarayonlari shakllarini ko'rib chiqadi. Biz asosiy tushunchalarni, ilg'or texnikalarni qamrab olamiz va global istiqbolni hisobga olgan holda amaliy misollar keltiramiz.
Modul Workerlarga Evolyutsiya: Oddiy Web Workerlardan Tashqari
Modul Workerlarni o'rganishdan oldin, ularning o'tmishdoshi - Web Workerlarni tushunish juda muhim. An'anaviy Web Workerlar JavaScript kodini alohida fon oqimida ishga tushirishga imkon beradi, bu esa uning asosiy oqimni bloklashini oldini oladi. Bu quyidagi vazifalar uchun bebahodir:
- Murakkab ma'lumotlarni hisoblash va qayta ishlash
- Tasvir va videoni manipulyatsiya qilish
- Uzoq vaqt talab qilishi mumkin bo'lgan tarmoq so'rovlari
- Ma'lumotlarni keshda saqlash va oldindan yuklash
- Haqiqiy vaqtda ma'lumotlarni sinxronizatsiya qilish
Biroq, an'anaviy Web Workerlarning ba'zi cheklovlari bor edi, ayniqsa modullarni yuklash va boshqarishda. Har bir worker skripti yagona, monolit fayl bo'lib, worker kontekstida bog'liqliklarni import qilish va boshqarishni qiyinlashtirardi. Bir nechta kutubxonalarni import qilish yoki murakkab mantiqni kichikroq, qayta ishlatiladigan modullarga bo'lish noqulay edi va ko'pincha worker fayllarining shishib ketishiga olib kelardi.
Modul Workerlar workerlarni ES Modullari yordamida ishga tushirishga ruxsat berib, bu cheklovlarni bartaraf etadi. Bu shuni anglatadiki, siz asosiy oqimda bo'lgani kabi, worker skriptingiz ichida to'g'ridan-to'g'ri modullarni import va eksport qilishingiz mumkin. Bu muhim afzalliklarni beradi:
- Modullik: Murakkab fon vazifalarini kichikroq, boshqariladigan va qayta ishlatiladigan modullarga bo'lish.
- Bog'liqliklarni Boshqarish: Standart ES Modul sintaksisi (`import`) yordamida uchinchi tomon kutubxonalarini yoki o'zingizning maxsus modullaringizni osongina import qilish.
- Kodni Tashkillashtirish: Fon jarayonlari kodingizning umumiy tuzilishini va saqlanuvchanligini yaxshilaydi.
- Qayta Ishlatiluvchanlik: Turli workerlar o'rtasida yoki hatto asosiy oqim va workerlar o'rtasida mantiqni almashishni osonlashtiradi.
JavaScript Modul Workerlarining Asosiy Tushunchalari
Mohiyatan, Modul Worker an'anaviy Web Worker kabi ishlaydi. Asosiy farq worker skriptining qanday yuklanishi va bajarilishida. JavaScript fayliga to'g'ridan-to'g'ri URL berish o'rniga, siz ES Modul URL-ni taqdim etasiz.
Oddiy Modul Worker Yaratish
Quyida Modul Workerni yaratish va ishlatishning asosiy misoli keltirilgan:
worker.js (modul worker skripti):
// worker.js
// Bu funksiya worker xabar olganda ishga tushadi
self.onmessage = function(event) {
const data = event.data;
console.log('Workerdagi qabul qilingan xabar:', data);
// Qandaydir fon vazifasini bajarish
const result = data.value * 2;
// Natijani asosiy oqimga qaytarib yuborish
self.postMessage({ result: result });
};
console.log('Modul Worker ishga tushirildi.');
main.js (asosiy oqim skripti):
// main.js
// Modul Workerlar qo'llab-quvvatlanishini tekshirish
if (window.Worker) {
// Yangi Modul Worker yaratish
// Eslatma: Yo'l modul fayliga (ko'pincha .js kengaytmali) ishora qilishi kerak
const myWorker = new Worker('./worker.js', { type: 'module' });
// Workerdan keladigan xabarlarni tinglash
myWorker.onmessage = function(event) {
console.log('Workerdan qabul qilingan xabar:', event.data);
};
// Workerga xabar yuborish
myWorker.postMessage({ value: 10 });
// Xatolarni ham qayta ishlashingiz mumkin
myWorker.onerror = function(error) {
console.error('Worker xatosi:', error);
};
} else {
console.log('Sizning brauzeringiz Web Workerlarni qo\'llab-quvvatlamaydi.');
}
Bu yerdagi asosiy narsa `Worker` instansiyasini yaratishdagi `{ type: 'module' }` opsiyasidir. Bu brauzerga taqdim etilgan URL-ni (`./worker.js`) ES Moduli sifatida ko'rib chiqishni aytadi.
Modul Workerlar bilan Aloqa
Asosiy oqim va Modul Worker (va aksincha) o'rtasidagi aloqa xabarlar orqali amalga oshiriladi. Ikkala oqim ham `postMessage()` metodiga va `onmessage` hodisa ishlovchisiga kirish huquqiga ega.
- `postMessage(message)`: Boshqa oqimga ma'lumot yuboradi. Ma'lumotlar odatda oqim izolyatsiyasini saqlash uchun to'g'ridan-to'g'ri almashinmasdan, nusxalanadi (tuzilgan klon algoritmi).
- `onmessage = function(event) { ... }`: Boshqa oqimdan xabar kelganda ishga tushadigan qayta chaqiruv funksiyasi. Xabar ma'lumotlari `event.data` da mavjud bo'ladi.
Murakkabroq yoki tez-tez aloqa uchun xabar kanallari yoki umumiy workerlar kabi shakllarni ko'rib chiqish mumkin, ammo ko'p hollarda `postMessage` yetarli bo'ladi.
Modul Workerlar bilan Ilg'or Fon Jarayonlari Shakllari
Endi, global foydalanuvchilar bazasiga qo'llaniladigan shakllardan foydalanib, yanada murakkab fon jarayonlari vazifalari uchun Modul Workerlardan qanday foydalanishni ko'rib chiqamiz.
Shakl 1: Vazifalar Navbati va Ishni Taqsimlash
Ko'p hollarda bir nechta mustaqil vazifalarni bajarish zarurati tug'iladi. Har bir vazifa uchun alohida worker yaratish o'rniga (bu samarasiz bo'lishi mumkin), siz vazifalar navbati bilan bitta worker (yoki workerlar hovuzi) dan foydalanishingiz mumkin.
worker.js:
// worker.js
let taskQueue = [];
let isProcessing = false;
async function processTask(task) {
console.log(`Vazifa qayta ishlanmoqda: ${task.type}`);
// Hisoblash jihatidan og'ir operatsiyani simulyatsiya qilish
await new Promise(resolve => setTimeout(resolve, task.duration || 1000));
return `Vazifa ${task.type} bajarildi.`;
}
async function runQueue() {
if (isProcessing || taskQueue.length === 0) {
return;
}
isProcessing = true;
const currentTask = taskQueue.shift();
try {
const result = await processTask(currentTask);
self.postMessage({ status: 'success', taskId: currentTask.id, result: result });
} catch (error) {
self.postMessage({ status: 'error', taskId: currentTask.id, error: error.message });
} finally {
isProcessing = false;
runQueue(); // Keyingi vazifani qayta ishlash
}
}
self.onmessage = function(event) {
const { type, data, taskId } = event.data;
if (type === 'addTask') {
taskQueue.push({ id: taskId, ...data });
runQueue();
} else if (type === 'processAll') {
// Navbatdagi har qanday vazifani darhol qayta ishlashga urinish
runQueue();
}
};
console.log('Vazifalar Navbati Workeri ishga tushirildi.');
main.js:
// main.js
if (window.Worker) {
const taskWorker = new Worker('./worker.js', { type: 'module' });
let taskIdCounter = 0;
taskWorker.onmessage = function(event) {
console.log('Worker xabari:', event.data);
if (event.data.status === 'success') {
// Muvaffaqiyatli vazifa bajarilishini qayta ishlash
console.log(`Vazifa ${event.data.taskId} natija bilan yakunlandi: ${event.data.result}`);
} else if (event.data.status === 'error') {
// Vazifa xatolarini qayta ishlash
console.error(`Vazifa ${event.data.taskId} bajarilmadi: ${event.data.error}`);
}
};
function addTaskToWorker(taskData) {
const taskId = ++taskIdCounter;
taskWorker.postMessage({ type: 'addTask', data: taskData, taskId: taskId });
console.log(`Vazifa ${taskId} navbatga qo'shildi.`);
return taskId;
}
// Foydalanish misoli: Bir nechta vazifa qo'shish
addTaskToWorker({ type: 'image_resize', duration: 1500 });
addTaskToWorker({ type: 'data_fetch', duration: 2000 });
addTaskToWorker({ type: 'data_process', duration: 1200 });
// Agar kerak bo'lsa, qayta ishlashni ixtiyoriy ravishda ishga tushirish (masalan, tugmani bosganda)
// taskWorker.postMessage({ type: 'processAll' });
} else {
console.log('Web Workerlar bu brauzerda qo\'llab-quvvatlanmaydi.');
}
Global Jihat: Vazifalarni taqsimlashda server yuklamasi va tarmoq kechikishini hisobga oling. Tashqi APIlar yoki ma'lumotlar bilan bog'liq vazifalar uchun, maqsadli auditoriyangiz uchun ping vaqtlarini minimallashtiradigan worker joylashuvlari yoki hududlarni tanlang. Masalan, agar foydalanuvchilaringiz asosan Osiyoda bo'lsa, ilovangizni va worker infratuzilmasini o'sha hududlarga yaqinroq joylashtirish samaradorlikni oshirishi mumkin.
Shakl 2: Og'ir Hisoblashlarni Kutubxonalar bilan Yengillashtirish
Zamonaviy JavaScript-da ma'lumotlar tahlili, mashinaviy o'rganish va murakkab vizualizatsiyalar kabi vazifalar uchun kuchli kutubxonalar mavjud. Modul Workerlar ushbu kutubxonalarni UI ga ta'sir qilmasdan ishga tushirish uchun idealdir.
Faraz qiling, siz gipotetik `data-analyzer` kutubxonasi yordamida murakkab ma'lumotlarni agregatsiyalashni xohlaysiz. Siz bu kutubxonani to'g'ridan-to'g'ri Modul Workeringizga import qilishingiz mumkin.
data-analyzer.js (misol kutubxona moduli):
// data-analyzer.js
export function aggregateData(data) {
console.log('Ma\'lumotlar workerda agregatsiyalanmoqda...');
// Murakkab agregatsiyani simulyatsiya qilish
let sum = 0;
for (let i = 0; i < data.length; i++) {
sum += data[i];
// Hisoblashni simulyatsiya qilish uchun kichik kechikish kiritish
// Haqiqiy senariyda bu haqiqiy hisoblash bo'ladi
for(let j = 0; j < 1000; j++) { /* kechikish */ }
}
return { total: sum, count: data.length };
}
analyticsWorker.js:
// analyticsWorker.js
import { aggregateData } from './data-analyzer.js';
self.onmessage = function(event) {
const { dataset } = event.data;
if (!dataset) {
self.postMessage({ status: 'error', message: 'Ma\'lumotlar to\'plami taqdim etilmagan' });
return;
}
try {
const result = aggregateData(dataset);
self.postMessage({ status: 'success', result: result });
} catch (error) {
self.postMessage({ status: 'error', message: error.message });
}
};
console.log('Tahlil Workeri ishga tushirildi.');
main.js:
// main.js
if (window.Worker) {
const analyticsWorker = new Worker('./analyticsWorker.js', { type: 'module' });
analyticsWorker.onmessage = function(event) {
console.log('Tahlil natijasi:', event.data);
if (event.data.status === 'success') {
document.getElementById('results').innerText = `Jami: ${event.data.result.total}, Soni: ${event.data.result.count}`;
} else {
document.getElementById('results').innerText = `Xato: ${event.data.message}`;
}
};
// Katta ma'lumotlar to'plamini tayyorlash (simulyatsiya)
const largeDataset = Array.from({ length: 10000 }, (_, i) => i + 1);
// Ma'lumotlarni qayta ishlash uchun workerga yuborish
analyticsWorker.postMessage({ dataset: largeDataset });
} else {
console.log('Web Workerlar qo\'llab-quvvatlanmaydi.');
}
HTML (natijalar uchun):
<div id="results">Ma'lumotlar qayta ishlanmoqda...</div>
Global Jihat: Kutubxonalardan foydalanganda, ularning samaradorlik uchun optimallashtirilganligiga ishonch hosil qiling. Xalqaro auditoriya uchun, worker tomonidan yaratilgan har qanday foydalanuvchiga ko'rsatiladigan natijalar uchun lokalizatsiyani hisobga oling, garchi odatda workerning natijasi asosiy oqim tomonidan qayta ishlanib, keyin ko'rsatiladi va lokalizatsiya shu yerda amalga oshiriladi.
Shakl 3: Haqiqiy Vaqtdagi Ma'lumotlarni Sinxronlash va Keshlash
Modul Workerlar doimiy ulanishlarni (masalan, WebSockets) saqlab turishi yoki mahalliy keshni yangilab turish uchun vaqti-vaqti bilan ma'lumotlarni olishi mumkin, bu esa ayniqsa asosiy serverlaringizga kechikishi yuqori bo'lgan hududlarda tezroq va sezgir foydalanuvchi tajribasini ta'minlaydi.
cacheWorker.js:
// cacheWorker.js
let cache = {};
let websocket = null;
function setupWebSocket() {
// Haqiqiy WebSocket manzilingiz bilan almashtiring
const wsUrl = 'wss://your-realtime-api.example.com/data';
websocket = new WebSocket(wsUrl);
websocket.onopen = () => {
console.log('WebSocket ulandi.');
// Boshlang'ich ma'lumotlarni yoki obunani so'rash
websocket.send(JSON.stringify({ action: 'subscribe', topic: 'updates' }));
};
websocket.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
console.log('WS xabari qabul qilindi:', message);
if (message.type === 'update') {
cache[message.key] = message.value;
// Asosiy oqimni yangilangan kesh haqida xabardor qilish
self.postMessage({ type: 'cache_update', key: message.key, value: message.value });
}
} catch (e) {
console.error('WebSocket xabarini tahlil qilishda xatolik:', e);
}
};
websocket.onerror = (error) => {
console.error('WebSocket xatosi:', error);
// Bir oz kechikishdan so'ng qayta ulanishga harakat qilish
setTimeout(setupWebSocket, 5000);
};
websocket.onclose = () => {
console.log('WebSocket uzildi. Qayta ulanmoqda...');
setTimeout(setupWebSocket, 5000);
};
}
self.onmessage = function(event) {
const { type, data, key } = event.data;
if (type === 'init') {
// Agar WS tayyor bo'lmasa, API-dan boshlang'ich ma'lumotlarni olish mumkin
// Sodda bo'lishi uchun, bu yerda WS ga tayanamiz.
setupWebSocket();
} else if (type === 'get') {
const cachedValue = cache[key];
self.postMessage({ type: 'cache_response', key: key, value: cachedValue });
} else if (type === 'set') {
cache[key] = data;
self.postMessage({ type: 'cache_update', key: key, value: data });
// Agar kerak bo'lsa, yangilanishlarni serverga yuborish
if (websocket && websocket.readyState === WebSocket.OPEN) {
websocket.send(JSON.stringify({ action: 'update', key: key, value: data }));
}
}
};
console.log('Kesh Workeri ishga tushirildi.');
// Ixtiyoriy: Agar worker to'xtatilsa, tozalash mantiqini qo'shish
self.onclose = () => {
if (websocket) {
websocket.close();
}
};
main.js:
// main.js
if (window.Worker) {
const cacheWorker = new Worker('./cacheWorker.js', { type: 'module' });
cacheWorker.onmessage = function(event) {
console.log('Kesh workerining xabari:', event.data);
if (event.data.type === 'cache_update') {
console.log(`Kalit uchun kesh yangilandi: ${event.data.key}`);
// Agar kerak bo'lsa, UI elementlarini yangilash
}
};
// Workerni va WebSocket ulanishini ishga tushirish
cacheWorker.postMessage({ type: 'init' });
// Keyinroq, keshdagi ma'lumotlarni so'rash
setTimeout(() => {
cacheWorker.postMessage({ type: 'get', key: 'userProfile' });
}, 3000); // Boshlang'ich ma'lumotlar sinxronizatsiyasi uchun biroz kutish
// Qiymatni o'rnatish uchun
setTimeout(() => {
cacheWorker.postMessage({ type: 'set', key: 'userSettings', data: { theme: 'dark' } });
}, 5000);
} else {
console.log('Web Workerlar qo\'llab-quvvatlanmaydi.');
}
Global Jihat: Haqiqiy vaqtdagi sinxronizatsiya turli vaqt zonalarida ishlatiladigan ilovalar uchun juda muhimdir. Kam kechikishli ulanishlarni ta'minlash uchun WebSocket server infratuzilmangiz global miqyosda tarqatilganligiga ishonch hosil qiling. Interneti beqaror bo'lgan hududlardagi foydalanuvchilar uchun mustahkam qayta ulanish mantiqini va zaxira mexanizmlarni (masalan, WebSockets ishlamay qolsa, davriy so'rovlar) joriy qiling.
Shakl 4: WebAssembly Integratsiyasi
O'ta samaradorlik talab etiladigan vazifalar, ayniqsa og'ir sonli hisoblashlar yoki tasvirni qayta ishlash bilan bog'liq bo'lganlar uchun WebAssembly (Wasm) deyarli tabiiy samaradorlikni taklif qilishi mumkin. Modul Workerlar Wasm kodini ishga tushirish uchun ajoyib muhit bo'lib, uni asosiy oqimdan izolyatsiya qilingan holda saqlaydi.
Sizda C++ yoki Rust-dan kompilyatsiya qilingan Wasm moduli (masalan, `image_processor.wasm`) bor deb faraz qiling.
imageProcessorWorker.js:
// imageProcessorWorker.js
let imageProcessorModule = null;
async function initializeWasm() {
try {
// Wasm modulini dinamik ravishda import qilish
// './image_processor.wasm' yo'li mavjud bo'lishi kerak.
// Wasm importlarini qayta ishlash uchun qurish vositangizni sozlashingiz kerak bo'lishi mumkin.
const response = await fetch('./image_processor.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.instantiate(buffer, {
// Kerakli xost funksiyalari yoki modullarni bu yerga import qiling
env: {
log: (value) => console.log('Wasm Log:', value),
// Misol: Workerdan Wasm-ga funksiya uzatish
// Bu murakkab, ko'pincha ma'lumotlar umumiy xotira (ArrayBuffer) orqali uzatiladi
}
});
imageProcessorModule = module.instance.exports;
console.log('WebAssembly moduli yuklandi va instansiyalandi.');
self.postMessage({ status: 'wasm_ready' });
} catch (error) {
console.error('Wasm-ni yuklash yoki instansiyalashda xatolik:', error);
self.postMessage({ status: 'wasm_error', message: error.message });
}
}
self.onmessage = async function(event) {
const { type, imageData, width, height } = event.data;
if (type === 'process_image') {
if (!imageProcessorModule) {
self.postMessage({ status: 'error', message: 'Wasm moduli tayyor emas.' });
return;
}
try {
// Wasm funksiyasi tasvir ma'lumotlariga va o'lchamlarga ko'rsatkich kutayotganini faraz qilish
// Bu Wasm bilan ehtiyotkorlik bilan xotirani boshqarishni talab qiladi.
// Umumiy shakl - Wasm-da xotira ajratish, ma'lumotlarni nusxalash, qayta ishlash, so'ngra qaytarib nusxalash.
// Sodda bo'lishi uchun, imageProcessorModule.process xom tasvir baytlarini qabul qiladi
// va qayta ishlangan baytlarni qaytaradi deb faraz qilamiz.
// Haqiqiy senariyda siz SharedArrayBuffer yoki ArrayBuffer uzatasiz.
const processedImageData = imageProcessorModule.process(imageData, width, height);
self.postMessage({ status: 'success', processedImageData: processedImageData });
} catch (error) {
console.error('Wasm tasvirini qayta ishlashda xatolik:', error);
self.postMessage({ status: 'error', message: error.message });
}
}
};
// Worker ishga tushganda Wasm-ni ishga tushirish
initializeWasm();
main.js:
// main.js
if (window.Worker) {
const imageWorker = new Worker('./imageProcessorWorker.js', { type: 'module' });
let isWasmReady = false;
imageWorker.onmessage = function(event) {
console.log('Tasvir workerining xabari:', event.data);
if (event.data.status === 'wasm_ready') {
isWasmReady = true;
console.log('Tasvirni qayta ishlash tayyor.');
// Endi siz qayta ishlash uchun tasvirlarni yuborishingiz mumkin
} else if (event.data.status === 'success') {
console.log('Tasvir muvaffaqiyatli qayta ishlandi.');
// Qayta ishlangan tasvirni ko'rsatish (event.data.processedImageData)
} else if (event.data.status === 'error') {
console.error('Tasvirni qayta ishlashda xatolik:', event.data.message);
}
};
// Misol: Qayta ishlash uchun tasvir faylingiz bor deb faraz qiling
// Tasvir ma'lumotlarini olish (masalan, ArrayBuffer sifatida)
fetch('./sample_image.png')
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
// Odatda bu yerda tasvir ma'lumotlarini, kenglikni, balandlikni ajratib olasiz
// Bu misol uchun, ma'lumotlarni simulyatsiya qilamiz
const dummyImageData = new Uint8Array(1000);
const imageWidth = 10;
const imageHeight = 10;
// Ma'lumotlarni yuborishdan oldin Wasm moduli tayyor bo'lishini kutish
const sendImage = () => {
if (isWasmReady) {
imageWorker.postMessage({
type: 'process_image',
imageData: dummyImageData, // ArrayBuffer yoki Uint8Array sifatida uzatish
width: imageWidth,
height: imageHeight
});
} else {
setTimeout(sendImage, 100);
}
};
sendImage();
})
.catch(error => {
console.error('Tasvirni olishda xatolik:', error);
});
} else {
console.log('Web Workerlar qo\'llab-quvvatlanmaydi.');
}
Global Jihat: WebAssembly global miqyosda ahamiyatli bo'lgan sezilarli samaradorlik o'sishini taklif etadi. Biroq, Wasm fayl hajmlari, ayniqsa cheklangan o'tkazuvchanlikka ega bo'lgan foydalanuvchilar uchun e'tiborga olinishi kerak. Wasm modullaringizni hajm bo'yicha optimallashtiring va agar ilovangizda bir nechta Wasm funksionalligi bo'lsa, kodni bo'lish kabi texnikalardan foydalanishni ko'rib chiqing.
Shakl 5: Parallel Qayta Ishlash uchun Worker Hovuzlari
Haqiqatan ham CPU-ga bog'liq bo'lgan va ko'plab kichik, mustaqil kichik vazifalarga bo'linishi mumkin bo'lgan vazifalar uchun workerlar hovuzi parallel bajarish orqali yuqori samaradorlikni ta'minlashi mumkin.
workerPool.js (Modul Worker):
// workerPool.js
// Vaqt oladigan vazifani simulyatsiya qilish
function performComplexCalculation(input) {
let result = 0;
for (let i = 0; i < 1e7; i++) {
result += Math.sin(input * i) * Math.cos(input / i);
}
return result;
}
self.onmessage = function(event) {
const { taskInput, taskId } = event.data;
console.log(`Worker ${self.name || ''} vazifa ${taskId}ni qayta ishlamoqda`);
try {
const result = performComplexCalculation(taskInput);
self.postMessage({ status: 'success', result: result, taskId: taskId });
} catch (error) {
self.postMessage({ status: 'error', error: error.message, taskId: taskId });
}
};
console.log('Worker hovuzi a\'zosi ishga tushirildi.');
main.js (Boshqaruvchi):
// main.js
const MAX_WORKERS = navigator.hardwareConcurrency || 4; // Mavjud yadrolardan foydalanish, standart 4
let workers = [];
let taskQueue = [];
let availableWorkers = [];
function initializeWorkerPool() {
for (let i = 0; i < MAX_WORKERS; i++) {
const worker = new Worker('./workerPool.js', { type: 'module' });
worker.name = `Worker-${i}`;
worker.isBusy = false;
worker.onmessage = function(event) {
console.log(`${worker.name}dan xabar:`, event.data);
if (event.data.status === 'success' || event.data.status === 'error') {
// Vazifa bajarildi, workerni bo'sh deb belgilash
worker.isBusy = false;
availableWorkers.push(worker);
// Agar mavjud bo'lsa, keyingi vazifani qayta ishlash
processNextTask();
}
};
worker.onerror = function(error) {
console.error(`${worker.name}da xatolik:`, error);
worker.isBusy = false;
availableWorkers.push(worker);
processNextTask(); // Tiklanishga harakat qilish
};
workers.push(worker);
availableWorkers.push(worker);
}
console.log(`Worker hovuzi ${MAX_WORKERS} ta worker bilan ishga tushirildi.`);
}
function addTask(taskInput) {
taskQueue.push({ input: taskInput, id: Date.now() + Math.random() });
processNextTask();
}
function processNextTask() {
if (taskQueue.length === 0 || availableWorkers.length === 0) {
return;
}
const worker = availableWorkers.shift();
const task = taskQueue.shift();
worker.isBusy = true;
console.log(`Vazifa ${task.id} ${worker.name}ga tayinlanmoqda`);
worker.postMessage({ taskInput: task.input, taskId: task.id });
}
// Asosiy ijro
if (window.Worker) {
initializeWorkerPool();
// Hovuzga vazifalar qo'shish
for (let i = 0; i < 20; i++) {
addTask(i * 0.1);
}
} else {
console.log('Web Workerlar qo\'llab-quvvatlanmaydi.');
}
Global Jihat: Mavjud CPU yadrolari soni (`navigator.hardwareConcurrency`) butun dunyodagi qurilmalar bo'ylab sezilarli darajada farq qilishi mumkin. Sizning worker hovuzi strategiyangiz dinamik bo'lishi kerak. `navigator.hardwareConcurrency` dan foydalanish yaxshi boshlanish bo'lsa-da, ba'zi foydalanuvchilar uchun mijoz tomonidagi cheklovlar hali ham to'siq bo'lishi mumkin bo'lgan juda og'ir, uzoq davom etadigan vazifalar uchun server tomonida qayta ishlashni ko'rib chiqing.
Global Modul Worker Implementatsiyasi uchun Eng Yaxshi Amaliyotlar
Global auditoriya uchun qurishda bir nechta eng yaxshi amaliyotlar juda muhimdir:
- Funksiyani Aniqlash: Har doim workerni yaratishga urinishdan oldin `window.Worker` qo'llab-quvvatlanishini tekshiring. Ularni qo'llab-quvvatlamaydigan brauzerlar uchun zaxira yechimlarini taqdim eting.
- Xatolarni Qayta Ishlash: Ham worker yaratishda, ham worker skriptining ichida mustahkam `onerror` ishlovchilarini joriy qiling. Xatolarni samarali tarzda qayd eting va foydalanuvchiga informativ fikr-mulohazalarni taqdim eting.
- Xotirani Boshqarish: Workerlar ichidagi xotira ishlatilishiga e'tibor bering. Katta ma'lumotlar uzatishlari yoki xotira sizib chiqishlari hali ham samaradorlikni pasaytirishi mumkin. Samaradorlikni oshirish uchun mos keladigan joylarda (masalan, `ArrayBuffer`) o'tkaziladigan obyektlar bilan `postMessage` dan foydalaning.
- Qurish Vositalari: Webpack, Rollup yoki Vite kabi zamonaviy qurish vositalaridan foydalaning. Ular Modul Workerlarni boshqarish, worker kodini paketlash va Wasm importlarini qayta ishlashni sezilarli darajada soddalashtirishi mumkin.
- Testlash: Fon jarayonlari mantiqingizni global foydalanuvchilar bazangizni ifodalovchi turli xil qurilmalar, tarmoq sharoitlari va brauzer versiyalarida sinab ko'ring. Kam o'tkazuvchanlikli va yuqori kechikishli muhitlarni simulyatsiya qiling.
- Xavfsizlik: Workerlarga yuboradigan ma'lumotlaringiz va worker skriptlaringizning manbalariga ehtiyot bo'ling. Agar workerlar maxfiy ma'lumotlar bilan ishlasa, to'g'ri tozalash va tekshirishni ta'minlang.
- Server Tomoniga O'tkazish: O'ta muhim yoki maxfiy operatsiyalar uchun yoki mijoz tomonida bajarish uchun doimiy ravishda juda talabchan bo'lgan vazifalar uchun ularni backend serverlaringizga o'tkazishni ko'rib chiqing. Bu mijozning imkoniyatlaridan qat'i nazar, izchillik va xavfsizlikni ta'minlaydi.
- Jarayon Ko'rsatkichlari: Uzoq davom etadigan vazifalar uchun fonda ish bajarilayotganini ko'rsatish uchun foydalanuvchiga vizual fikr-mulohazalarni (masalan, yuklanish belgilari, jarayon satrlari) taqdim eting. Jarayon yangilanishlarini workerdan asosiy oqimga uzating.
Xulosa
JavaScript Modul Workerlari brauzerda samarali va modulli fon jarayonlarini ta'minlashda muhim yutuqni ifodalaydi. Vazifalar navbati, kutubxonalarni yengillashtirish, real vaqtda sinxronizatsiya va WebAssembly integratsiyasi kabi shakllarni qabul qilish orqali dasturchilar xilma-xil global auditoriyaga xizmat qiladigan yuqori samarali va sezgir veb-ilovalarni yaratishlari mumkin.
Ushbu shakllarni o'zlashtirish sizga hisoblash jihatidan og'ir vazifalarni samarali hal qilish imkonini beradi va silliq va qiziqarli foydalanuvchi tajribasini ta'minlaydi. Veb-ilovalar murakkablashib, foydalanuvchilarning tezlik va interaktivlikka bo'lgan talablari o'sishda davom etar ekan, Modul Workerlar kuchidan foydalanish endi hashamat emas, balki jahon darajasidagi raqamli mahsulotlarni yaratish uchun zaruratdir.
JavaScript ilovalaringizda fon jarayonlarining to'liq salohiyatini ochish uchun bugunoq ushbu shakllar bilan tajriba o'tkazishni boshlang.