• בלוג
  • שאלת ראיונות עבודה: הבטחות ב JavaScript (שוב?? כן שוב, נו הכי כיף Promises)

שאלת ראיונות עבודה: הבטחות ב JavaScript (שוב?? כן שוב, נו הכי כיף Promises)

23/11/2021

נוד 16 הכניסו מודול של timers/promises שמאפשר להפעיל את setTimeout בתור Promise, אז השאלה הפעם תשתמש ב Node.JS. ויהיה גם פיתרון כי תכל'ס זה הדבר המעניין לכתוב עליו.

1. השאלה

נתונה התוכנית הבאה ב Node.JS:

import {
  setTimeout,
} from 'timers/promises';

async function waitAndSayYay() {
  await setTimeout(1000);
  console.log('yay');
}

for (let i=0; i < 10; i++) {
  waitAndSayYay();
}

התוכנית מחכה 10 שניות ואז מדפיסה על המסך 10 פעמים את המילה yay. וכן צריך Node 16 בשביל להריץ אותה וצריך לשמור את הקוד בקובץ עם סיומת .mjs.

האתגר שלכם - מבלי לשנות את לולאת ה for שבסוף התוכנית, עדכנו את הקוד כך שהלולאה תחכה שניה בין הדפסה להדפסה כלומר סך הכל התוכנית תרוץ במשך 10 שניות.

2. פיתרון: שימוש ב Promise חיצוני

אז קל לראות את הבעיה כאן - כל הפעלה של waitAndSayYay היא עצמאית ולא יודעת שכבר קראו לפונקציה כמה פעמים קודם. הפיתרון הוא להשתמש ב Promise גלובאלי כדי לסנכרן בין הקריאות:

  1. אגדיר Promise גלובאלי שלא עושה כלום

  2. כל פעם שמפעילים את waitAndSayYay הוא יוסיף בלוק then ל Promise הגלובאלי, וגם יעדכן את ה Promise הגלובאלי שישמור את התוצאה - כלומר עם בלוק then החדש. בתוך אותו בלוק then תהיה פקודה לחכות שניה ואז להדפיס yay.

  3. בתוך הפונקציה אפעיל await על ה Promise הגלובאלי, מה שאומר שאני מחכה לכל ה Promise-ים שהיו עד עכשיו ואחריהם לבלוק then החדש שלי.

בקוד זה נראה ככה:

import {
  setTimeout,
} from 'timers/promises';

let running = new Promise((resolve, reject) => { resolve() });

async function waitAndSayYay() {
  running = running.then(async () => {
    await setTimeout(1000);
    console.log('yay');
  });
  await running;
}

for (let i=0; i < 10; i++) {
  waitAndSayYay();
}

טריק כזה יכול להועיל כשיש לנו פונקציה אסינכרונית שעושה משהו רגיש ולא היינו רוצים פונקציות אחרות "שיתפרצו" באמצע. לדוגמה פונקציה כותבת מספר קבצים לדיסק ורוצה לוודא שקוד אסינכרוני אחר לא ירוץ לפני שהיא תסיים לכתוב את כל הקבצים.

יש לכם רעיונות אחרים איך לממש את המנגנון? מוזמנים כרגיל לשתף בתגובות.