שלום אורח התחבר

שאלות מראיונות עבודה: אנגולר

הזינו את כתובת המייל וקבלו את הפוסט היומי בכל בוקר אליכם לתיבה:

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

1השאלה

מה השגיאה שתקבלו בעת הפעלת הקוד הבא? מה גורם לה וכיצד כדאי לתקן?

<div ng-app="myApp" class="container">  
  <div ng-controller="mainCtrl as vm">
    <ul>
      <li ng-repeat="user in vm.slice(4) track by $index">{{user.name}}</li>
    </ul>
  </div>
</div>
var app = angular.module('myApp', []);
app.controller('mainCtrl', MainCtrl);

function MainCtrl() {
  var vm = this;
  vm.users = ['martin', 'jane', 'bill', 'barbara', 'tim', 'layla', 'martha', 'harry'];

  vm.slice = function(n) {
    return vm.users.slice(0,n).map(function(name) { return { name: name } });
  }; 
}

 

2תיאור הבעיה

הקוד עובד ומציג רשימה של 4 שמות מתוך המערך. יחד עם זאת הוא גם בקונסול את הודעת השגיאה Infinite $digest Loop. הגורם לשגיאה הוא פשוט קסום: אנגולר יפעיל את הפונקציה slice כדי לייצר את הרשימה ולאחר מכן יפעיל אותה שוב בלולאה עד ש״הערך יתייצב״. הרעיון הוא שפונקציה זו יכולה להביא לשינוי במשתנים מסוימים או מקומות אחרים שידרשו שערוך מחדש ולכן זיהוי השינויים ב Scope מתבצע בלולאה.
אבל רגע הרי הפונקציה slice מחזירה מערך עם אותם הערכים כל פעם— למה שתהיה כאן בעיה? בכל הפעלה לכאורה אנו מקבלים מערך עם שמות ארבעת האנשים הראשונים. 

התשובה היא שאנגולר אכן מסתכל על הערכים במערך אך במקרה שלנו אלו לא אותם ערכים בשתי הפעלות עוקבות, מאחר ובכל הפעלה הפוקנציה מייצרת אובייקטים חדשים בתוך המערך (שימו לב שאין בעיה להחזיר מערך חדש עם אותם האובייקטים, לכן slice לבד לא תגרום לבעיה). 

פונקציה שמחזירה מערך ונקראת מתוך ה Digest Loop חייבת להחזיר בשתי הפעלות עוקבות מערך עם אותם הערכים בדיוק (אם אכן שום דבר לא השתנה).

3רעיונות לפתרון

אחרי שמבינים את הבעיה אפשר לדבר על הפתרון, ולמעשה זה החלק הקל. כך למשל אפשר להעביר את ה map מחוץ לפונקציית slice:

function MainCtrl() {
  var vm = this;
  vm.users = _.map(['martin', 'jane', 'bill', 'barbara', 'tim', 'layla', 'martha', 'harry'], function(name) { return { name: name }} );

  vm.slice = function(n) {
    return vm.users.slice(0,n);
  }; 
}

 


נהניתם מהפוסט? מוזמנים לשתף ולהגיב