لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 06/20/15 في كل الموقع
-
عامٌ ونصف قد مضت منذ بدء عملي على شركات ناشئة أو كمطور ويب أجير، كان ذلك عقب تخرّجي من جامعة وارويك؛ حيث عملت كمطوّر ويب، وإنه لمن دواعي سروري أن أشارككم بعض أفكاري حول كيفيّة إدارة الشركات الناشئة بدون تمويل خارجي؛ إذ سأتحدث في هذا المقال عن منهج "العمل وفق أمواج" (“working in waves”). أمواج؟تحول الكثير من الأسباب عادةً بينك وبين إطلاق شركتك الناشئة؛ سيقول البعض أن ما يجعل منك رياديًا ناجحًا هو أن تستمرّ بالعمل على فكرتك مع وجود هذه المخاوف؛ ولعلّ التمويل هو أحد أكبر المخاوف التي تواجهنا؛ إذ غالبًا ما نفكّر أننا بحاجة لمبلغ معيّن من المال قبل أن تتمكّن من الانطلاق. من الطرق التي تمكّنك من تحصيل ما يكفيك لتمويل مشروعك العمل بدوامٍ كامل (أو بشكل مكثّف جدًا) لمدّة ما بشكلٍ مأجور؛ تجمع من خلاله مبلغًا ماليًا يساعدك على قضاء الفترة التالية؛ متفرغًا للعمل على مشروعك فقط بوقتِ كامل (أو حتى أكثر من ذلك). أسمّي هذه الطريقة "العمل وفق أمواج". لماذا نختار هذا المنهج؟من الممكن أن يبدو "العمل وفق أمواج" فكرة جذّابة؛ إذ تسمح لك التركيز الكامل على مشروعك طيلة فترة محددة؛ ويعتمد طول هذه الفترة على المقدار الذي جنيته من المال في الفترة السابقة لها، ولكي تبقى في أمان مادي يتوجب عليك تخمين معدّل الاستنفاد burn rate* المتوقّع لمشروعك قبل الشروع بتنفيذه؛ الأمر الذي سيُطلعك على الوقت الذي تنفد فيه الأموال من جعبتك؛ ويجعلك تعمل تحت ضغط شديد لإطلاق المشروع أثناء "الموجة" الحالية. وهكذا يتيح العمل بهذا المنهج التركيز الكامل مع الضغط اللازم لإعلان الإنطلاقة؛ وهما مفردتان أساسيتان للنجاح، أليس كذلك؟ إذا كنت محظوظًا، لن تحتاج إلّا لموجة واحدةالسيناريو المثالي لهذا المنهج يتمثّل في ادّخارك لمالٍ كافٍ قبل الدخول في "موجة" مشروعك، ثم البدء بالعمل عليه، ليسيرَ بعدها كلُّ شيء وفقَ ما خطّطته حرفيًّا، وتبدأ بعذ ذلك في الحصول على الأرباح مُحققًا "ربحية الكفاف" بشكل ذاتيّ، أو تحصل على تمويل جديد قبل أن تنفذ الأموال من يديك. لستُ أدري بطبيعة الحال كيف تجري الأمور بالنسبة لكلّ منكم؛ لكنّني ومع بعض الخبرة بالشركات الناشئة؛ تعلّمت أن أقلّل فرضيّاتي قدر المستطاع؛ وأن أفحص هذه الافتراضات بصرامة. لذا أتوقّع أنه سيكون من المستبعد للغاية إطلاقُ شركتك بعد موجة عمل واحدة فحسب؛ حاولتُ شخصيًّا ذلك لكنني لم أنجح، يتحدّث ستيف بلانك كثيرًا عن هذا: "ما لم تكن محظوظًا بشكلٍ لا يُصدّق؛ فإن معظم افتراضاتك ستكون خاطئة، ما يحدث بعد ذلك سيكون مؤلمًا، متوقَّعًا، ويمكن تجنّبه، لكنه على الرغم من ذلك فهو مكوّن أساسي ضمن خطّة عمل أية شركة ناشئة". مشاكل العمل وفق أمواجتبعًا لتجربتي؛ فإن القضية الرئيسية في العمل الموجيّ أثناء بنائك شركتك الناشئة؛ هو أنّك ستحتاج حتمًا فترة أطول مما تعتقد؛ ما يعني أن الوقت -وبالتالي المال- سينفذ منك. ولعلّ نفاد المال -أو حتى الاقتراب من ذلك- من أكثر الأمور ضررًا بالشركات الناشئة؛ فهو يؤثر على إنتاجيتك، بصيرتك، وعلى حماستك أيضًا، إذ تعلم أنك ستحتاج قريبًا للعمل مجدّدًا بغية ادّخار النقود لموجة لاحقة من إتمام بناء مشروعك، وهذا يعني أيضًا أن حركة تطوير منتجك ستصبح أبطأ مما خطّطت له، لهذا أتساءل شخصيّا فيما إذا كان "العمل وفق أمواج" هو أحد المناهج الأقلّ تفضيلًا لبناء الشركات الناشئة من دون تمويل. طرقٌ أخرى لتمويل شركتك الناشئةبعد تجربتي لمنهجيةّ "العمل وفق أمواج"، والعمل على شركتك النّاشئة كمشروع جانبي، أتأمل حاليًّا فيما إذا كان هنالك مناهج أخرى لتمويل الشّركات النّاشئة، الأمر الذي يجعلني أفكّر أكثر فأكثر بـ "ربحية الكفاف"؛ أتساءل كم ستكون الأمور مختلفةً عندما تشعُر بأنّ الجانب المعيشيّ من حياتك مؤمَّن أثناء بنائك شركتك الناشئة، أعتقدُ أنّها ستصنع فارقًا كبيرًا في الأداء، وأتمنى أن أكون محظوظًا كفاية لتجربة هذا الفارق ومشاركتكم إياه. ما هي أفكاركم أو تجاربكم حول تمويل فكرة ما؟ يسعدني أن أسمع منكم. burn rate* أو معدّل الاستنفاد: مقياس لسرعة صرف أية شركة أو مشروع لرأس المال الخاص بها. تُرجم وبتصرّف عن مقال Ways to bootstrap a startup: "working in waves" لصاحبه Joel Gascoigne.2 نقاط
-
تحدثنا في الأجزاء السابقة من سلسلة مقالات "كيف تُصبح مُستقلاً ناجحًا" عن العمل المُستقل عمومًا موضحين أبرز ميزاته، ثُمّ عرّجنا على الخطوات العملية الأولى للعمل المُستقل وتعرفنا على أدواته اللازمة وتوسعنا إلى مجموعة من الأساسيات للترويج عن الأعمال المُستقلة وأفضل الطرق لإيجاد العملاء. ثُمّ انطلقنا معكم مُرتكزين على توجيه العروض وسياسات التسعير المُتّبعة في هذا العمل، وشرحنا تفاصيل إدارة العمليات والحصول على التقييمات وطرق استقبال الأموال. وجاء المقال السابق من السلسلة لينقل لكم المشاكل التي تعترض العمل المُستقل والمُستقلين عمومًا موضحين أبرز الحلول التي يُمكن اتباعها في سبيل تخطي تلك المشاكل والعقبات. سنختتم سلسلة مقالاتنا بتوجيهات حول الآليات المُناسبة لإدارة وقتك كمُستقل ضمن فضاء الإتقان بالعمل لتحقيق مُحصلة تتمثل بأفضل قيمة للعمل ضمن أقل وقت تنفيذ. إدارة الوقت والإتقان في أي عمل قائم في هذه الحياة وأثناء نموه وتطوّره تتوارد لصاحبه ومضات تنبؤه بأهمية الوقت وأهمية استغلاله ضمن نطاقٍ سليم بهدف تنظيم الإنتاجية وبالتالي تحصيل عامل الإتقان الذي يُضفي إلى الربحية والمزيد منها. العمل المُستقل لا يخرج عن هذا السياق، على العكس فإن هذا النوع من الأعمال يحتاج إلى ضبط أكبر للوقت، وكما تحدثنا فيما سبق ضمن المشاكل العشرة الأبرز للعمل المستقل بأن أحد أكبر الفوارق بين العمل الحُر والعمل الوظيفي هو أن الأخير مُحدّد بساعات دوام، بينما العمل الحر يصعب تقييده بوقتٍ مُحدّد، إضافة إلى أن طبيعة العمل من خلال الانترنت تحديداً تفرض وجود طلبات شراء واتصالات من طرف الزبائن على مدار الساعة. لذلك إن لم تكن لديك كمُستقل قدرة عالية على ضبط الوقت والالتزام به فستخرج الأمور عن السيطرة وستكون النتيجة هي الفشل حتمًا. كيف أرتّب وقتي كمُستقل خلص معظم الناجحين في هذه الحياة إلى أن استغلال الوقت واستثماره بأفضل شكل يُعدّ (فنًا) وهو السر الكبير من أسرار النجاح والذي دفعنا إلى تخصيص هذا القسم من سلسلتنا لأهميته. حينما نتحدّث عن الوقت هُنا فنحن نربطه بشكلٍ مُباشر بالإنتاجية. فمعنى أن يكون وقت عملك مُمتلئ طوال اليوم فهذا لا يعني أبداً أن تكون مُنتجًا (قد تستغرق لإنجاز مُهمّة طيلة اليوم، وقد تُحسن التصرّف بالتركيز وتوزيع الوقت بشكل أنسب لأدائها وتُنجزها خلال وقتٍ أقل وبنفس الجودة). إذاً ليس بالضرورة أن من يعمل لوقتٍ أطول سيُنجز أكثر وهذا السر الذي لا يُمكن سوى أن يكون واضح تمامًا لأي إنسان ناجح في حياته العملية. نصائح في إدارة الوقت للمُستقلين 1. الوقت هو الكنز: عليك أن تُعوّد نفسك كمُستقل وأن تنسخ ذلك في ثنايا عقلك الباطن بأن أكبر قيمة لديك هي وقتك، بحيث تكون على تأهّب كامل بشكل لا شعوري، ويكون فقدانك لأي جزء من الوقت سببًا لإحساسك بالذنب والخسارة الحقيقية. 2. رتّب مهامك ونظّم أولويات عملك: الترتيب والتنظيم أساس لإنجاز أي عمل مُثمر. هُناك العديد من أساليب إدارة الوقت والتنظيم، كما أن نظريات ودراسات وتحليلات عديدة أطلقت في هذا السياق وأثبتت فضل انعكاس التنظيم على العمل. نصيحتنا الأساسية لك هي أن تكون وحدك مدير وقتك بحيث تضع الضوابط وفق ما يُناسبك، والأهم أن تلتزم بتلك الضوابط وأن تُقيمها بالتجريب وتصوبها إن اقتضت الحاجة. والتالي قائمة بتلميحات عامّة ستُرشدك بهذا السياق: قُم بإعداد قائمة بالمهام اليومية وقسّم تلك المهام طبقًا للأولويات. (لاحظ: في العمل المُستقل من خلال الإنترنت فإن المشروع صاحب أقرب وقت للتسليم يوضع على رأس أولويات الإنجاز، ثُمّ الذي يليه من حيث تاريخ التسليم ... وهكذا). راجع مهامك اليومية وأدائها خلال وقت مُحدّد من اليوم، وفكّر قبل النوم بمهام اليوم التالي. حدّد وقت لكل شيء ولا تخلط بين الأمور (وقت للعمل – وقت للراحة – وقت لتسويق خدماتك أو مُنتجاتك ...الخ). لا تُرهق نفسك في التشدّد في التنظيم وحاول أن تتدرّج بالموضوع. (لاحظ: إن الشدّة في التطبيق في الأيام الأولى قد تُرتّب عليك مفعولاً عكسيًا عند شعورك بالإرهاق أو الملل من النظام، لذلك حاول أن تجعل من الأمر عادة تُمارسها بالتدريج). 3. ابتعد عن المُلهيات: أصبحت حياتنا اليومية مليئة بالمُلهيات، وحتى إن استثنينا وجود أفراد العائلة (الإخوة، الزوجة، الأولاد، ...) في حالة المُستقلين الذين يعملون في منازلهم، فإن هُنالك العديد من المُلهيات التي تُضيّع أوقاتنا دون أن نشعر. التالي بعض النصائح البسيطة التي ندعوك لاتباعها أثناء العمل للتوصّل لأفضل أداء: اجعل مكان العمل مُنظمًا على الدوام، نظيف ومُريح نفسيًا وجسديًا. أغلق هاتفك المحمول أو أبعده تمامًا عنك أثناء العمل. ابتعد عن شبكات التواصل الاجتماعي تمامًا أثناء العمل. (نعم بشكلٍ قاطع). لا تستخدم الإنترنت أثناء العمل سوى لتلبية أمور مُتعلقة بالإنجاز، وأغلق أي شاشات عرض أثناء العمل. أغلق جميع الإشعارات الآلية التي من المُمكن أن تصلك من حاسبك أو هاتفك أو جهازك اللوحي. ضع جميع ما يُمكن أن تحتاجه أثناء عملك في مُتناول يدك. أبلغ من هم معك (في المنزل، في المكتب، ...) بأوقات عملك كي لا يترددوا إليك في هذه الأوقات ويشغلوا تركيزك. خذ فترات مُنتظمة من الراحة مُبتعداً فيها عن جو العمل تمامًا ومُمارسًا بها تمرينًا مُعينًا أو شيئًا تُحبه. 4. ساعد عميلك في الحفاظ على وقتك: إن كان لديك مُنتج جاهز يُباع بنسخ مُتعدّدة، أو خدمة تعمل على تنفيذها فإنه من الأفضل أن توفّر معلومات وافية حول هذه الخدمة أو هذا المُنتج. (وجود فيديو تعريفي يشرح الخدمة أو المُنتج هو أمر جيد، كذلك وجود سرد للمعلومات على شكل الأسئلة الشائعة FAQ هو جيّد وسيحدّ من هدر الوقت في الإجابة على الاستفسارات). 5. قلّص وقت التسليم بقدر المُستطاع بالتناسب مع تطوّرك: إن كان مجال عملك المُستقل في تقديم الخدمات فعليك مع زيادة الخبرة تقليص (تقريب) وقت التسليم بشكل تدريجي مع الحفاظ على الجودة ودون إغفال حجم الطلب المُتوقّع، وبالتالي استغلال فائض الوقت في أعمال أخرى أو في التسويق لأعمالك. 6. ركّز على مشروع واحد بقدر المُستطاع: حاول أن تنتهي من كل عمل تُنفذه بشكل كامل ثُمّ تنتقل للعمل الذي يليه. هذا الأمر سيضبط التركيز ويُحافظ على الوقت بالمُحصلة. مثال عملي إن كان عملك المُستقل في مجال تصميم المُنتجات واستقبلت خلال مرحلة زمنية مُعينة ثلاثة تصاميم جديدة لها أوقات تسليم مُتتابعة. أغلق أولاً إمكانية استقبال أي طلبات جديدة إن لم تكن لديك القدرة على تلبية المزيد أو عدّل في أوقات تسليم الطلبات الجديدة بزيادته ثُم قٌم على الفور بضبط المهام الواردة (التصاميم الثلاثة) وحدّد لها أوقات انتهاء تتناسب مع وقت تنفيذ كلٍ منها (اجعل لنفسك عامل أمان درءًا لأي إشكال قد يحصل) ثُمّ اعمل على تنفيذ التصاميم بحسب الخطة الموضوعة بحيث يتم البدء بالتصميم الأول والتركيز على أداءه وإنهاءه بشكل كامل وتسليمه، ثُمّ البدء في الثاني بعد انتهاء الأول، ثُمّ الثالث بعد انتهاء الثاني. (العمل على التصاميم الثلاثة في ذات الوقت سيُسبّب التشتّت وعدم الدقّة في العمل). 7. خصّص وقتًا لمُتابعة الطلبات والإشعارات: كعامل مُستقل من خلال الإنترنت سواء في بيع المُنتجات الجاهزة أو تنفيذ الخدمات فإنه من الطبيعي أن تتلقى مُراسلات دائمة من الزبائن والمُهتمين (بعضها قد تكون استفسارات بسيطة قبل الشراء، وبعضها الآخر قد يُناقش مُشكلة لدي الزبون ويقتضي التفرّغ لحلها ...الخ) تلك المُراسلات والإشعارات سواء أكانت واردة على منصات العمل الحُر أو على البريد الإلكتروني أو وسائل الاتصال الأخرى التي تستخدمها أثناء عملك تحتاج إلى تفرّغ بشكل خاص دون دمج مع العمل، لأنها قد تُسبّب التشتّت أثناء العمل وبالتالي ينعكس الأمر سلبًا على أداءه وبخاصة إن كانت أعمالك لها علاقة بالمجالات البرمجية أو الإبداعية. لذلك يُنصح دومًا بأن تُخصّص أوقات مُحدّدة خلال اليوم (مثلاً ساعة كل 6 ساعات) بحيث تتفحص خلالها المُراسلات والإشعارات وتُجيب عليها. 8. استفد من أدوات تنظيم الوقت: نظراً للأهمية الكبيرة في مجال إدارة الوقت فقد توفّرت مئات الأدوات المُفيدة التي بالإمكان استغلالها بغرض التنظيم والتي جاءت على شكل تطبيقات سطح مكتب، مواقع ويب وكذلك تطبيقات للهواتف الذكية. من الجيّد أن تبحث وتُجرّب ما يُناسبك وتعتمده لتنظيم أوقاتك. تلميح: رغم أننا نعيش في عصرٍ معلوماتي إلّا أن كثيراً من الأفراد ما زالوا يأنسون الورقة والقلم ويعتمدون عليهما في جدولة المهام، ولا نُنكر أبداً بأنها طريقة فعّالة ولا بأس أبداً باعتمادها. تبيع بكثرة؟ ليس بالضرورة أن تكون الأفضل! لا توجد مُشكلة مع العنوان... كعامل مُستقل فأنت تبني اسمك وسمعتك مع نجاح هذا العمل. من المُهم للغاية أن تكون أعمالك مُتقنة ومُنفّذة بشكل سليم في حال كُنت صاحب خدمات مهما صغُرت تلك الخدمات أو كبر حجمها، أيضًا في حال كُنت من أصحاب المُنتجات الإلكترونية ذات النُسخ المعروضة للبيع المُتكرّر فمن المُهم أن تكون تلك النُسخ ذاتية الصُنع غير منسوخة أو مُقرصنة، احترام اسمك واحترام المهنة سيفرضان عليك ذلك بالتأكيد. الاغترار بالبيع السريع (لدى نسبة سيئة من المُستقلين) لمُنتجات أو تقديم خدمات مُخالفة (اختراق مواقع، قرصنة ملفات وبيعها، ...) قد تُحقّق لهم ربحًا سريعًا على المدى القصير فقط، إلّا أن الأساس المغلوط سيُنهي الأمر وستنتهي معه سُمعة المُستقل. يُخبرنا أجدادنا بأن العمل من الشرف وأن بناء السُمعة قد تحتاج لأشهر وسنوات طويلة، إلّا أن هدمها قد لا يأخذ سوى دقائق معدودة، لذلك ندعو كافّة المُستقلين الجُدد بأن يُعبروا عن أنفسهم بأفضل شكل مُمكن وأن يكونوا مُعتزين بأعمالهم وخطواتهم الواثقة. الخاتمة كُنا معكم في سلسلة من مقالاتٍ ستّة جاءت تحت عنوان (كيف تُصبح مُستقلاً ناجحًا) ناقشت بشكلٍ عملي جميع المراحل التي يحتاجها الفرد بغرض وضع أول خطوة له في العمل المُستقل من خلال تعريفه بهذا النوع من الأعمال وأهميتها في وقتنا الراهن مرورًا بالأدوات اللازمة وطرق العمل والتسعير وآليات الترويج وتقديم العروض وغيرها من التفاصيل المطلوبة للسير وفق منهج صحيح، ثُمّ تطرقنا إلى جوانب أوسع بحيث وضحنا أبرز المشاكل والعقبات التي تعترض هكذا نوع من الأعمال وناقشنا الحلول لتخطيها، وانتهينا بتوضيح أهمية الإدارة الصحيحة للوقت في العمل المُستقل إضافة إلى إتقان العمل. كلمة الكاتب عليك أن تضع هدفك الواضح وتؤمن بقدراتك وإمكانياتك لتحقيق هذا الهدف، عليك أن تسعى وتجّتهد بسعيك بعد التوكّل على الله عزّ وجل. الإنترنت لم يعد مكانًا للعب وإضاعة الوقت وغُرفًا للدردشة التي لا تُسمن ولا تُغني من جوع، الإنترنت بات الأرض الخصبة للعمل وبناء العلاقات، أرضًا تُعطي خيرًا وفيرًا لمن يزرع بذور الإرادة العالية والاجتهاد. لا تقل أبدًا نحن في وطنٍ عربيٍ لا يقدّر الكفاءات، اعمل وكُن أحد صُنّاع المُستقبل. لم يعد لديك أي عُذر فالباب مفتوح على مصراعيه أمامك. كُن مُستقلاً...1 نقطة
-
SSE اختصار لـ Server Sent Events وتسمى أيضًا EventSource تُستخدم لِبنّاء تطبيقات ويب تفاعلية. حيث يُرسل الخادوم أحداثا في الوقت الحقيقي إلى المستخدم، قد يتضمن الحدث تنبيهات للمستخدم أو بيانات يمكن استغلالها في عمل شيء ما وتحديث صفحة الويب. في السّابق، لِعمل تحديث تلقائي للبيانات كل ثانية كانت تُستَخدم هذه الطريقة: setInterval(function(){ // إستدعاء الدالة بشكل تكراري xhr = new XMLHttpRequest(); // إستخدام طلب ajax xhr.onreadystatechange = function(){// عند أي تغير في حالة الطلب if(this.readyState == 4){// تم إستقبال النص بنجاح // إفعل بعض الاوامر } } xhr.open("get","http://localhost"); // تحديد نوع الطلب ورابط الموقع xhr.send("mydata"); // إرسال البيانات إلى الخادم }, 1000); // تحديد مدّة التكرار إلى ثانية أو هذه الطريقة الأكثر تطورًا: function getAjax(){ // تعريف الدالة التي ستدعى بشكل تكراري xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(this.readyState == 4) setTimeout(function(){ // استدعاء ألدالة مجددًا بعد ثانية من الإنتهاء لِتكرار طلب الajax getAjax(); },1000); } xhr.open("get","http://localhost"); xhr.send("mydata"); } getAjax();// إستدعاء الدالة للمرة الأولىهذه الطرق صحيحة لكنها ليست الأفضل، حيث تقوم بإرسال طلب كل ثانية للخادم مما يُسبٍّب ضغط عليه وغالبًا لا يكون التحديث في الوقت الحقيقي لظهوره. فكرة عمل SSE أن الطلب يظل مَفتوحا في إنتظار محتوى جديد والخادم هو من يُرسل المحتوى الجديد وليس المتصفح من يطلبه. SSE ليست الطريقة الوحيدة لِبناء تطبيقات ويب تفاعلية، يوجد العديد من الطرق الأخرى من أشهرها WebSocket. مُقارنة بين SSE و WebSocketالسهولة والتوافقيةمعظم الإستضافات المشتركة لا تَدعم WebSocket وهو يعمل على بروتوكل ws أو wss (في حالة إستخدام شهادة أمان ssl) وهما مختلفان عن الذي عليه واجهة المستخدم مما يُسبِّب مشاكل في مصادفة الاثنين معًا (يوجد مكتبات لفعل ذلك) على خلاف SSE التي تُعتبر طلب عادي على نفس بروتوكول واجهة المستخدم النهائية. تزامن المتسخدمينWebSocket يُمكنها عمل تزامن بين المستخدمين بطريقة مباشرة حيث أن الإتصلات تُعالج كلها معًا. في SSE لايوجد طريقة مباشرة لِتزامن المسخدمين معًا لأن كل طلب مُنفصل عن الآخر لذا تُستخدم قاعدة بيانات وتحفظ أخر التغيرات للمستخدم الأول وعند المستخدم الآخر يَتم البحث بشكل دوري عن التغيرات في قاعدة البيانات ثم إرسالها إلى المستخدم الآخر. إرسال وإستقبال البياناتWebSocket و SSE يدعمان إستقبال البيانات لكن لا يُمكن إرسال البيانات إلى الخادم بإستخدام SSE، أي عند بناء تطبيق يعتمد على إرسال وإستقبال البيانات من الخادوم ستضطر إلى بناء صفحة منفصلة تقوم بإستقبال الطلبات من المستخدم بواسطة ajax مثلًا. تطبيقات قد يكون إستخدام WebSocket فيها أفضلفي تطبيق سيحتاج إلى تفاعل المستخدمين معًا (تطبيق تواصل مثلًا) سيكون إستخدام WebSocket أفضل من SSE لأن الأخيرة لا يُمكنها إستقبال الطلبات من الخادوم.إرسال إشعارات أو رسائل للمستخدم أو أي تطبيق لن يَحتاج المستخدم فيه إلى إرسال رسائل إلى الخادوم. هنا ممكن أن يكون إستخدام SSE أفضل وأسهل.اهلًا بالعالمقبل البدء يجب أن تَعرف المتصفحات الداعمة لـِ SSE وأن متصفح أنترنت أكسبلور لايَدعمه لكن يُمكنك إستخدام مكتبة خارجية لدعمه مثل EventSource.js (يتم تضمين ملف javascript في الصفحة) هذا مثال لنص مصدري لإستجابة طلب SSE: http/1.1 200 OK ## الصفحة موجودة ! Content-Type: text/event-stream ## تعريف المتصفح أن الصفحة هي محتوى لطلب SSE event: delete## تعريف الحدث الذي سيُستقبل من javascript data: "some data" ## البيانات التي سترسل إلى الحدث event: add## تعريف حدث آخر data: "some data" data: "some data"## إرسال بيانات بدون حدث مُعرف id: 3 ## غير مهم وغير مطلوب بشكل ضروري يُستخدم لتحديد مُعرف lastEventId للرسائلالأمثلة مكتوبة بلغة php ويُمكنك فعلها في أي لغة ويب أخرى هذا تطبيق بسيط لجلب الساعة من الخادم لحظة بلحظة. ملف server.php ( الذي سيعالج طلبات SSE احفظه بجوار واجهة المستخدم أو أي مكان آخر مع تغير المسار في شفرة javascript ): <?php set_time_limit(0);// تحديد أقصى مدة للطلب غير نهائية لان هناك خوادم تقوم بتحديدها $time = 1;// متغير بقيمة الوقت الذي سيرسل فيه تحديث جديد header("Content-Type: text/event-stream");// إرسال ترويسة أن الصفحة هي محتوى sse header('Cache-Control: no-cache'); // لمنع حفظ الكاش للصفحة while(true){// تكرار /* date("s-i-h") تُخرج الوقت على التَنسيق ساعة-دقيقة-ثانية PHP_EOL تعني سطر جديد يُمكن إستخدام \n لكن سَتختلف من نظام تَشغيل الى آخر */ echo "data: ".date("s-i-h").PHP_EOL; echo PHP_EOL; // كتابة نص جديد آخر للتفريق بين التنبيهات // إرسال المحتوى الذي كتب دون الإنتظار إلى انتهاء الصفحة ob_flush(); flush(); // إيقاف الاسكربت إلى المدة التي تم تعريفها في المتغير time لمدة ثانية أن لم تَقف الاسكربت سَيعمل بدون توقف sleep($time); } ?>إن فتحت الصفحة ستجد أنها تقوم بإرسال الساعة الحالية كل ثانية. الآن الواجهة التي ستتعامل معها: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> </head> <body style="direction: rtl"> <label>الساعة الآن : <span>.......</span></label> <script type="text/javascript"> if(!EventSource) alert("مٌتصفحك لايَدعم SSE :("); else{ SSE = new EventSource("server.php"); // انشاء الطلب SSE.onmessage = function(ms){ // عند وجود رسالة جديدة document.querySelector("span").innerHTML = ms.data;// استبدال النص بالجديد } SSE.onerror = function(){//عند وجود خطأ alert("يوجد خطأ في الاتصال ..."); mkcon(); // إعادة الطلب } } </script> </body> </html> الأحداث وطرق انشاءهايُمكن في SSE إنشاء أحداث مخصصة لكي تَكون الشفرة أكثر ذكاءا، مثلًا إرسال حدث لحذف عنصر وحدث لإنشاء عنصر آخر. مثال: تعريف مصفوفة بإسم الألوان أحمر أخضر أزرق. $colors = array("red", "green", "blue");ثم تعريف اسم الحدث بإسم عشوائي من هذه الألوان: $colors[rand(0,2)];ليكون النص الكامل لملف server.php: <?php set_time_limit(0);// تحديد أقصى مدة للطلب غير نهائية لان هناك خوادم تقوم بتحديدها $time = 1;// متغير بقيمة الوقت الذي سيرسل فيه تحديث جديد header("Content-Type: text/event-stream");// إرسال ترويسة أن الصفحة هي محتوى sse $colors = array( // مصفوفة الألوان من النوع الرقمي "red", "green", "blue" ); while(true){// تكرار /* date("s-i-h") تُخرج الوقت على التَنسيق ساعة-دقيقة-ثانية PHP_EOL تعني سطر جديد يُمكن إستخدام \n لكن سَتختلف من نظام تَشغيل إلى آخر */ echo "data: ".date("s-i-h").PHP_EOL; echo "event: ". $colors[rand(0,2)] // توليد لون عشوائي بإسم الحدث .PHP_EOL; echo PHP_EOL; // كتابة نص جديد آخر للتفريق بين التنبيهات // إرسال المحتوى وعدم الإنتظار إلى إكتمال الطلب إلى النهاية ob_flush(); flush(); // إيقاف الاسكربت إلى المدة التي تم تعريفها في المتغير time لمدة ثانية أن لم تَقف الاسكربت سَيعمل بدون توقف sleep($time); } ?>وفي واجهة المستخدم إنشاء بعض العناوين: <style> .red{ color: red } .blue{ color: blue } .green{ color: green } </style> <label class="red"> ....... </label> <label class="green"> ....... </label> <label class="blue"> ....... </label>الآن إستقبال الأحداث: SSE.addEventListener("red",function(ms){ //اللّون الأحمر red اسم الحدث الذي عرف من php document.querySelector(".red").innerHTML = ms.data; });لتصبح شفرة الواجهة الكاملة: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <style> .red{ color: red } .blue{ color: blue } .green{ color: green } </style> </head> <body> <label class="red"> ....... </label> <label class="green"> ....... </label> <label class="blue"> ....... </label> <script type="text/javascript"> if(!EventSource) alert("مٌتصفحك لايَدعم SSE :("); else{ function mkcon(){ SSE = new EventSource("server.php"); // إنشاء الطلب SSE.addEventListener("red",function(ms){ //اللون الأحمر document.querySelector(".red").innerHTML = ms.data; }); SSE.addEventListener("green",function(ms){ //اللون الأخضر document.querySelector(".green").innerHTML = ms.data; }); SSE.addEventListener("blue",function(ms){ //اللون الأزرق document.querySelector(".blue").innerHTML = ms.data; }); SSE.onerror = function(){//عند وجود خطأ alert("يوجد خطأ في الاتصال ..."); mkcon(); // اعادة الطلب } } mkcon(); } </script> </body> </html>ستجد أن أحدى الساعات من الثلاثة تزيد بشكل عشوائي كل ثانية لكن بالطبع هذا مثال، لن تقوم بإستخدام هذه التقنية في هذا. إستخدام بيانات jsonإن أردت إرسال مقال بإستخدام SSE فستحتاج إلى إرسال العنوان والمحتوى ولن تُرسل حدثين لذلك يُمكنك إستخدام json كما يلي: { "title": "العنوان", "content": "المحتوى" }اذًا سَترسل هذه البيانات: data: {"title": "ألعنوان","content":"ألمحتوى"}ثم سيكون إستقبال البيانات من خلال javascript بهذا الشكل: SSE.onmessage = function(ms){ var JsonData = JSON.parse(ms.data); // قراءة نص json alert(JsonData.title + "\n" + JsonData.content); }مثال عملي عن إرسال بيانات json بتوقيت السيرفر المحلي: ملف server.php <?php set_time_limit(0);//تُحدد أقصى مدة للطلب غير نهائية لان هناك خوادم تقوم بتحديدها $time = 1;// متغير بقيمة الوقت الذي سيرسل فيه تحديث جديد header("Content-Type: text/event-stream");// إرسال ترويسة أن الصفحة هي محتوى sse while(true){// تكرار /* date("s-i-h") تُخرج الوقت على التَنسيق ساعة-دقيقة-ثانية PHP_EOL تعني سطر جديد يُمكن إستخدام \n لكن سَتختلف من نظام تَشغيل الى آخر */ echo 'data: '. /** مصفوفة بالوقت. دالة json_encode تقوم بتحويل البيانات الى ترميز json */ json_encode(array( "hour" => date("h"), // الساعة "minute" => date("i"), // الدقيقة "second" => date("s") // الثانية )) .PHP_EOL; echo PHP_EOL; // كتابة نص جديد آخر للتفريق بين التنبيهات // إرسال المحتوى وعدم الإنتظار إلى إكتمال الطلب إلى النهاية ob_flush(); flush(); // إيقاف الاسكربت إلى المدة التي تم تعريفها في ألمتغير time لمدة ثانية ان لم تَقف الاسكربت سَيعمل بدون توقف sleep($time); } ?>وملف الواجهة: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> </head> <body style="direction: rtl"> <p>الساعة الآن <b id="hour">0</b> و <b id="minute">0</b> دقيقة و <b id="second">0</b> ثانية.</p> <script type="text/javascript"> if(!EventSource) alert("مٌتصفحك لايَدعم SSE :("); else{ function mkcon(){ SSE = new EventSource("server.php"); // إنشاء الطلب SSE.onmessage = function(ms){ var JsonData = JSON.parse(ms.data); // قراءة نص json document.querySelector("#hour").innerHTML = JsonData.hour; // إستبدال الساعة document.querySelector("#minute").innerHTML = JsonData.minute;// إستبدال الدقائق document.querySelector("#second").innerHTML = JsonData.second;// إستبدال الثواني } SSE.onerror = function(){//عند وجود خطأ alert("يوجد خطأ في الاتصال ..."); mkcon(); // إعادة الطلب } } mkcon(); } </script> </body> </html>في هذا المثال والذي سبقه لن تَحتاج إلى إستحدام SSE ويمكن عَمل ذلك بإستخدام javascript بسهولة. تطبيق على ما شُرح: بناء تطبيق تواصللم تُستخدم قاعدة بيانات لتسهيل تشغيل السكربت (لكن بالطبع إستخدام قاعدة بيانات أفضل) سيولد لون لكل مستخدم وسيحفظ في cookies للتعرف عليه في الرسائل، ستحفظ البيانات في ملف ChatData.json على هذا الشكل (كان يُمكن إستخدام قاعدة بيانات sqlite): [// مصفوفة الرسائل { "author": "rgb(54,48,98)", // لون السمتخدم "message": "رسالة", }, { "author": "rgb(54,48,98)", // لون السمتخدم "message": "رسالة 2", }// ....,...,.. ]تصميم الواجهةهذه هيكلة الصفحة: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>تجربة</title> <meta name="viewport" content="width=device-width"> </head> <body> <div class="messages"> </div> <div class="form"> <div class="author me"></div> <textarea placeholder="كتابة رسالة"></textarea> <button id="send">أرسل</button> </div> </body> </html>إضافة الحيوية للصفحة: body,html{ width: 100%;/** جعل عرض الصفحة بكامل الشاشة **/ direction: rtl; height: 100%; background: #f0f0f0;/** لون الخلفية **/ padding: 0; margin: 0 } /** جعل حجم بعض العناصر يحسب بالحواشي الخارجة **/ .messages, .messages > .message, .message > .content, .form, .form > textarea{ box-sizing: border-box } /** الرسائل **/ .messages{ padding: 40px; /** عمل فراغ بقيمة 40px من كل جهة **/ height: 80%; overflow-y: auto/** جعل الرسائل الزائدة تتحول الى اسكرول **/ } /** عناصر لن تكون بكامل عرض الحافظة **/ .message > .author, .message > .content{ display: inline-block;/** لن يأخذ العنصر كامل العرض **/ vertical-align: top /** العنصر سيكون في محاذة الأعلى **/ } /** هوية المستخدم **/ .message > .author{ width: 64px; height: 64px; background: #ddd; /** اللون الافتراضي سيغير بعد ذلك **/ border-radius: 100% /** تدوير العنصر **/ } /** جسم الرسالة **/ .message > .content{ background: white; box-shadow: 0 0 1px #ccc; /** تأثير الظل **/ padding: 20px; margin-right: 30px; /** لجعل الصفحة أكثر إستجابة على الشاشات المختلفة **/ width: 100%; max-width: 550px } /** عناصرالتحكم لإرسال رسالة **/ .form{ padding: 10px; height: 20% } /** صندوق النصوص **/ .form > textarea{ width: 100%; max-width: 678px; height: 100% } /** زر الإرسال **/ .form > button{ background: rgb(31, 158, 238); padding: 4px 20px; border: 0; cursor: pointer; /** مؤشر الفارة **/ color: white; border-radius: 3px /** عمل بعض الحواف **/ } .form > button:active{ background: rgb(31, 158, 200) } /** تصميم الجوال إصلاح بعض العلل **/ @media screen and (max-width:640px){ .messages{ padding: 0 } .message > .content{ margin: 0; margin-bottom: 20px } }إستقبال الرسائلSEE لاتدعم إرسال البيانات إلى الخادوم لذا سَتستخدم ajax لذلك. هذه شفرة بسيطة لإرسال الرسائل إلى الخادوم (يُضاف بين الوسم script في أخر الصفحة قبل </body> أو إن كنت ستضيفه الى head، يجب أن يكون في دالة: window.onload = function(){ //هنا }; document.querySelector("#send").addEventListener("click",function(){// عند الضغط على زر إرسال var mss = document.querySelector(".form > textarea").value; // محتوى الرسالة if(mss && mss.length){// التأكد من أن الرسالة مكتوبة var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function(){ if(this.readyState == 4) alert("تم إرسال الرسالة"); } ajax.open("get","server.php"); // نوع الطلب ومسار الإرسال ajax.send("?ms="+mss);// إرسال الرسالة } });ستحدث مشكلة إن أرسل المستخدم أكثر من رسالة في وقت واحد، من الممكن أن تصل رسالة قبل الأخرى. لذا سنستعمل قائمة بالرسائل المرسلة ونقوم بمعالجتها واحدة ثم الأخرى مع تحسين تجربة المستخدم قليلًا: messagesList = []; // مصفوفة بالرسائل InProgress = false;// يوجد طلب يُعالج أم لا function sendFirstMessage(){ if(!messagesList.length || InProgress) // لايوجد رسائل أو هناك رسالة تُعالج return false; var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function(){ // الرسالة ارسلت if(this.readyState == 4){ messagesList.splice(0, 1);// حذف الرسالة المرسلة اول رسالة InProgress = false; // تم الإنتهاء من العمل sendFirstMessage(); // إرسال الرسالة الأخرى } } ajax.onerror = function(){ alert("خطأ في الإتصال جاري المحاولة مجددًا"); sendFirstMessage(); } InProgress = true; ajax.open("get","send.php?message="+messagesList[0]); // نوع الطلب ومسار الإرسال ajax.send();// إرسال الرسالة } document.querySelector("#send").addEventListener("click",function(){// عند الضغط على زر إرسال var mss = document.querySelector(".form > textarea").value; // محتوى الرسالة if(mss && mss.length){// التأكد من أن هناك رسالة مكتوبة messagesList.push(mss); // إضافة رسالة إلى المصفوفة sendFirstMessage(); // إرسال الرسالة الأولى document.querySelector(".form > textarea").value = "";// افراغ حقل إرسال الرسائل } });ملف الخادوم الذي سيستقبل الرسائل، لن تكتب [] في الملف لتسهيل الكتابة في نهايته دون قِرائته: ملف send.php (الذي سيستقبل الرسائل) <?php if(empty($_GET["message"])) die(); /* التأكد من المستخدم */ if(!isset($_COOKIE["author"]) || !preg_match("/^rgb\([0-9]{0,3}\,[0-9]{0,3}\,[0-9]{0,3}\)$/i",$_COOKIE["author"])){ // توليد لون عشوائي أن لم يُعرف من قبل $R = rand(0,250); // اللّون الأحر $G = rand(0,250); // اللّون الأخضر $B = rand(0,250); // اللّون الأزرق setcookie("author","rgb($R,$G,$B)"); // نمط الألوان rgb } $message = str_replace(array("<",">"),array("<",">"),$_GET["message"]); // الوقاية من ثغرة xss $data = array( // البيانات التي ستكتب "content" => $message, "author" => $_COOKIE["author"] ); $FILE = fopen("./ChatData.json","a"); //فتح الملف للكتابة فيه $star = (!filesize("./ChatData.json")) ? "" :",";// إضافة فاصلة أن تم الكتابة بالملف من قبل fwrite($FILE,$star.json_encode($data)); // كتابة بيانات json في الملف fclose($FILE); ?>ملاحظة: سبب إستخدام الألوان هو لكي تتمكن من التعامل مع المستخدمين وحفظ البيانات في قاعدة البيانات للمستخدم. ملف server.php (الذي سيراقب تغير الملف ويرسل التحديث) <?php set_time_limit(0); // لايوجد اقصى مدة للطلب header("Content-Type: text/event-stream"); $viewd = 0; // عدد الرسائل التي عرضت لمنع إرسال الرسالة اكثر من مرة $lastFileSize = 0; // حجم الملف عندما يتغير فان هناك رسالة ارسلت while(true){ if(filesize("./ChatData.json") >= $lastFileSize){// التحديث فقط عند تغير حجم الملف $messages = json_decode("[".file_get_contents("./ChatData.json")."]"); // قراءة الرسائل for($i=$viewd;$i<=sizeof($messages)-1;$i++){ // حلقة تكرار من أخر رسالة مُرسلة echo "data: ".json_encode($messages[$i]).PHP_EOL; echo PHP_EOL; } $viewd = sizeof($messages); // تحديث عدد الرسائل المرسلة $lastFileSize = filesize("./ChatData.json"); // تحديث مُتغير أخر حجم للملف } ob_flush(); flush(); sleep(1); } ?>ثم في واجهة المستخدم شفرة javascript لجلب التحديثات: sse = new EventSource("server.php"); // انشاء الاتصال sse.onmessage = function(ms){ var data = JSON.parse(ms.data); // قراءة بيانات json var message = document.createElement("div"); // عنصر الرسائل message.setAttribute("class","message"); // اضافة كلاسس message var author = document.createElement("div"); // عنصر مُرسل الرسائل author.setAttribute("class","author"); // اضافة كلاسس author author.style.backgroundColor = data.author; // تغير لون الخلفية لمعرف المستخدم message.appendChild(author); // اضافة عنصر مُعرف مُعرف المستخدم الى عنصر الرسالة var content = document.createElement("p"); // محتوى الرسالة content.setAttribute("class","content"); content.innerHTML = data.content;// محتوى الرسالة message.appendChild(content); messages = document.querySelector(".messages"); messages.appendChild(message);// اضافة عنصر الرسالة الى حافظة الرسائل messages.scrollTop = messages.scrollHeight; // انزال الاسكرول الى الاعلى } ليعمل على انترنت اكسبلور يجب تضمين ملف javscript هذا في الـ header: <script src="https://rawgithub.com/remy/polyfills/master/EventSource.js"></script> يجب ان يكون العمل مُطابق لهذا: إن لم يعمل معك بشكل صحيح يُمكنك تحميل ملفات الأمثلة وقراءتها حتى تتمكن من معرفة كيف يعمل هذا المثال . الخاتمةيُمكنك رؤية المزيد من المصادر لمعرفة المزيد حول SSE: eventsource من طرف W3C.Server Sent Events من طرف مدونة موزيلا للمبرمجين.1 نقطة