Search code examples
javascriptobjectundefined

Don't return object if undefined?


I'm hoping someone might be able to help out here, or point me in the right direction.

  1. I'm using an external API, to find out which flights are available, on which days. (Response is mm_newJson).
  2. I'm then creating a new object obj = {};, to store/push the values I need for each day, (the date and fare).
  3. And then, I'm matching the obj.date to my calendar days, and inserting the fare value, whenever there is a value.

For some days, there are no values in my object. And therefore, returns undefined.

Here's a screenshot, of what my object looks like, in this scenario:

enter image description here

The problem:

Where the object is undefined, (because there is no object.date or object.fare key/values), I do not want the object.fare to be inserted into my calendar.

In this scenario, "undefined" appears in my calendar.

I've patched up this issue, by replacing "undefined", with an empty string " " . But basically, I just don't want object.fare to be returned at all, if it is undefined.

My code is below and I have tried adding my conditions in the function below. Eg:

if (typeof object === 'object'), or if (object == 'undefined'), or

My however, I'm not sure how to resolve this.

I just don't want the object.value to be inserted, if it is undefined. As undefined appears on the matching calendar days, when I don't want it to.

window.mm_newJson = [];
window.mm_dailyPrice = [];
window.mm_fullDate = new Date();
window.mm_startDate = String(mm_fullDate.getFullYear()) + '-' + String(mm_fullDate.getMonth()+1) + '-' +  String(mm_fullDate.getDate());

// FETCH DATE AVAILABILITY
const response = await fetch('https://www.MYAPI.COM');
mm_newJson = await response.json();

// Loope through API to find each month
for (let i=0; i < mm_newJson.Months.length; i++) {
  console.log(mm_newJson.Months[i].FlightDates);

  // Find fares which are available in month
  for (let j = 0; j < mm_newJson.Months[i].FlightDates.length; j++) {
    let obj = {};
    // Grab the specific dates
    obj['date'] = String(mm_newJson.Months[i].YearNumber) + '-' + String(('0' + String(mm_newJson.Months[i].MonthNumber)).slice(-2)) + '-' + String(('0' + (mm_newJson.Months[i].FlightDates[j])).slice(-2));
    obj['fare'] = "WW";
    mm_dailyPrice.push(obj);
  };
};

// Search mm_dailyPrice for date
function searchDate(input) {
  let object = mm_dailyPrice.find(el => el.date === input);
  console.log("object", object)
  if (object != undefined) {
    return object.fare;
  } else {
    // Returns undefined, if I do not handle else condition
    return "n/a";
  }
};


// Add AVAILABILITY
let days = document.querySelector('div[data-tab*="Date Calendar Outbound"]').querySelectorAll('.day');
let j = 0;

// For each day in the 12 month calendar, display the "fare" value
for (let i = 0; i < days.length; i++) {
  let date = days[i].dataset.date;
  if (days[i].firstElementChild){
    let fare = searchDate(date);

    // if (fare !== "undefined") {
      console.log("fare", fare);
      let priceSpan = document.createElement('span');
      priceSpan.innerHTML = String(fare);
      priceSpan.setAttribute('class', 'calendar-price-test');
      days[j].appendChild(priceSpan);
      j++;
    // }
  }
};

Here's how my calendar looks, if the object is undefined, (but in this screenshot, I've replaced undefined with a string, so undefined doesn't appear on the relevant day.

But really, I don't want anything for these days to appear at all. So I don't want object.fare to be identified, if it's undefined. IE - I don't want it to appear in the calendar.

enter image description here

Here's also a screenshot of the response, after the initial fetch, if that helps. The numbers in FlightDates, represents the days of the month, where I'd like to inject "WW" only.

enter image description here


Solution

  • I don't have all the information I need so I hope I can help you (it would be optimal to have a json example of the data returned by the API).

    A javascript function can return undefined this way:

    // Search mm_dailyPrice for date
    function searchDate(input) {
      let object = mm_dailyPrice.find(el => el.date === input);
      console.log("object", object)
      if (object != undefined)
        return object.fare;
      
      return;
    };
    

    But when you check with this line of code (currently commented):

    if (fare !== "undefined") {
    

    you must test for undefined not "undefined", or you can test for the latter using typeof:

    if (fare !== undefined) {
    

    or

    if (typeof fare !== "undefined") {
    

    Personally I prefer the former, the other one can be confusing.

    As you can see your code is working correctly.

    window.mm_newJson = [];
    window.mm_dailyPrice = [];
    window.mm_fullDate = new Date();
    window.mm_startDate = String(mm_fullDate.getFullYear()) + '-' + String(mm_fullDate.getMonth()+1) + '-' +  String(mm_fullDate.getDate());
    
    mm_newJson = {
        Months: [
            {MonthNumber: 8, YearNumber: 2021, FlightDates: [4, 6, 15, 18, 20, 22]},
            {MonthNumber: 9, YearNumber: 2021, FlightDates: [4, 5, 6, 8, 12, 13, 15, 16, 14, 19, 20, 22]},
            {MonthNumber: 10, YearNumber: 2021, FlightDates: [3, 5, 6, 8, 12, 13, 15, 16, 14, 19, 20, 22]},
            {MonthNumber: 11, YearNumber: 2021, FlightDates: [3, 6, 8, 13, 16, 18, 20, 22]},
            {MonthNumber: 12, YearNumber: 2021, FlightDates: [3, 5, 6, 8, 12, 13, 15, 16, 18, 19, 20, 22]},
            {MonthNumber: 1, YearNumber: 2022, FlightDates: [2, 5, 6, 8, 12, 13, 15, 16, 18, 19, 20, 22]},
            {MonthNumber: 2, YearNumber: 2022, FlightDates: [2, 5, 6, 8, 12, 13, 16, 18, 17, 24]},
            {MonthNumber: 3, YearNumber: 2022, FlightDates: [2, 5, 6, 8, 11, 13, 15, 18, 17, 24]},
            {MonthNumber: 4, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 11, 13, 15, 16, 17, 25]},
            {MonthNumber: 5, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 10, 13, 15, 16, 18, 25]},
            {MonthNumber: 6, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 10, 13, 15, 16, 18, 25]},
            {MonthNumber: 7, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 10, 13, 15, 16, 18]},
            {MonthNumber: 8, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 18, 19, 20, 22]},
            {MonthNumber: 9, YearNumber: 2022, FlightDates: [1, 5, 6, 8, 13, 16, 19, 22]}
        ]
    };
    
    // Loope through API to find each month
    for (let i=0; i < mm_newJson.Months.length; i++) {
      // Find fares which are available in month
      for (let j = 0; j < mm_newJson.Months[i].FlightDates.length; j++) {
        let obj = {};
        // Grab the specific dates
        obj['date'] = String(mm_newJson.Months[i].YearNumber) + '-' + String(('0' + String(mm_newJson.Months[i].MonthNumber)).slice(-2)) + '-' + String(('0' + (mm_newJson.Months[i].FlightDates[j])).slice(-2));
        obj['fare'] = "WW";
        mm_dailyPrice.push(obj);
      }
    }
    
    // Search mm_dailyPrice for date
    function searchDate(input) {
      let object = mm_dailyPrice.find(el => el.date === input);
    
      if (object !== undefined)
        return object.fare;
    
        return false;
    }
    
    
    // Add AVAILABILITY
    //let days = document.querySelector('div[data-tab*="Date Calendar Outbound"]').querySelectorAll('.day');
    let days = [
        {dataset: {date: "2022-08-01"}},
        {dataset: {date: "2022-08-02"}},
        {dataset: {date: "2022-08-03"}},
        {dataset: {date: "2022-08-04"}},
        {dataset: {date: "2022-08-05"}},
        {dataset: {date: "2022-08-06"}},
        {dataset: {date: "2022-08-07"}},
        {dataset: {date: "2022-08-08"}},
        {dataset: {date: "2022-08-09"}},
        {dataset: {date: "2022-08-10"}},
        {dataset: {date: "2022-08-11"}},
        {dataset: {date: "2022-08-12"}},
        {dataset: {date: "2022-08-13"}},
        {dataset: {date: "2022-08-14"}},
        {dataset: {date: "2022-08-15"}},
        {dataset: {date: "2022-08-16"}},
        {dataset: {date: "2022-08-17"}},
        {dataset: {date: "2022-08-18"}},
        {dataset: {date: "2022-08-19"}},
        {dataset: {date: "2022-08-20"}},
        {dataset: {date: "2022-08-21"}},
        {dataset: {date: "2022-08-22"}},
        {dataset: {date: "2022-08-23"}},
        {dataset: {date: "2022-08-24"}},
        {dataset: {date: "2022-08-25"}},
        {dataset: {date: "2022-08-26"}},
        {dataset: {date: "2022-08-27"}},
        {dataset: {date: "2022-08-28"}},
        {dataset: {date: "2022-08-29"}},
        {dataset: {date: "2022-08-30"}}
    ];
    
    let j = 0;
    
    let list = document.querySelector(".list");
    console.log(mm_newJson.Months[12]);
    
    // For each day in the 12 month calendar, display the "fare" value
    for (let i = 0; i < days.length; i++) {
      let date = days[i].dataset.date;
      //if (days[i].firstElementChild){
        let fare = searchDate(date);
    
        if (fare !== false) {
          let priceSpan = document.createElement('span');
          priceSpan.innerHTML = "date " + date + ", fare " + String(fare);
          priceSpan.setAttribute('class', 'calendar-price-test');
          //days[j].appendChild(priceSpan);
          
          let item = document.createElement('li');
          item.appendChild(priceSpan);
          list.appendChild(item);
          
          //j++;
          console.log(j, "date", date, "fare", fare);
        }
      //}
    }
    <ul class="list"></ul>

    Instead, the error lies in the presentation, in using two different indexes i and j to specify from which calendar day to read the reference date (i) and on which calendar day to insert the span (j).

    Since j is only incremented when searchDate does not return undefined you will always see all dates with WW consecutively.


    As a side note I recommend that you modify the structure of the mm_dailyPrice array to have faster and easier access to the data.

    You could use an object (dictionary) instead of an array and specify as keys the first part of the UTC date (YYYY-MM) or YYYY-MM-01 and as the value the array with the days of the month already returned by the API (and other optional data you can need) without scanning mm_dailyPrice every time.

    I can't write you an example because I don't know how you will use the fare property.