Home > database >  Code works fine when value is hardcoded, but fails when value is dynamic
Code works fine when value is hardcoded, but fails when value is dynamic

Time:12-30

I'm working on a chrome extension that grabs data from Rate My Professor's GraphQL API and then puts that rating on my universities courses portal. Here's my code:

background.js

const {GraphQLClient, gql} = require('graphql-request');
console.log("background.js loaded");

const searchTeacherQuery = gql`
query NewSearchTeachersQuery($text: String!, $schoolID: ID!)
{
  newSearch {
    teachers(query: {text: $text, schoolID: $schoolID}) {
      edges {
        cursor
        node {
          id
          firstName
          lastName
          school {
            name
            id
          }
        }
      }
    }
  }
}
`;


const getTeacherQuery = gql`
query TeacherRatingsPageQuery(
  $id: ID!
) {
  node(id: $id) {
    ... on Teacher {
      id
      firstName
      lastName
      school {
        name
        id
        city
        state
      }
      avgDifficulty
      avgRating
      department
      numRatings
      legacyId
      wouldTakeAgainPercent
    }
    id
  }
}
`;

const AUTH_TOKEN = 'dGVzdDp0ZXN0';

const client = new GraphQLClient('https://www.ratemyprofessors.com/graphql', {
  headers: {
    authorization: `Basic ${AUTH_TOKEN}`
  }
});

const searchTeacher = async (professorName, schoolID) => {
  console.log("searchTeacher called");
  console.log(professorName);
  console.log(typeof professorName);
  console.log(schoolID);
  const response = await client.request(searchTeacherQuery, {
    text: professorName,
    schoolID
  });

  if (response.newSearch.teachers === null) {
    return [];
  }

  return response.newSearch.teachers.edges.map((edge) => edge.node);
};

const getTeacher = async (id) => {
  const response = await client.request(getTeacherQuery, {id});

  return response.node;
};

async function getAvgRating(professorName) {
  console.log('1: ', professorName);
  const teachers = await searchTeacher(professorName, 'U2Nob29sLTE0OTU=');
  console.log(teachers);
  const teacherID = teachers[0].id;
  const teacher = await getTeacher(teacherID);
  const avgRating = teacher.avgRating;
  console.log(teacher);
  console.log(avgRating);

  return avgRating;
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  console.log('received message from content script:', request);
  console.log('test:', request.professorName);

  getAvgRating(request.professorName).then(response => {
    sendResponse(response);
  });
  return true;
});

and here's content.js:

const professorLinks = document.querySelectorAll('td[width="15%"] a');

professorLinks.forEach(link => {
  const professorName = link.textContent;
  console.log(professorName);
  
  chrome.runtime.sendMessage({ professorName }, (response) => {

    console.log(response);

    if (response.error) {
      link.insertAdjacentHTML('afterend', `<div>Error: ${response.error}</div>`);
    } else {
      link.insertAdjacentHTML('afterend', `<div>${response}/5</div>`);
    }

  });
});

Now, if I set professorName to a fixed value, like this:

async function getAvgRating(professorName) {
  const teachers = await searchTeacher('Hossein Kassiri', 'U2Nob29sLTE0OTU=');
  console.log(teachers);
  const teacherID = teachers[0].id;
  const teacher = await getTeacher(teacherID);
  const avgRating = teacher.avgRating;
  console.log(teacher);
  console.log(avgRating);

  return avgRating;
}

the code works as intended, with the expected output: expected output

but if searchTeacher is called with professorName instead of a fixed value like this:

async function getAvgRating(professorName) {
  const teachers = await searchTeacher(professorName, 'U2Nob29sLTE0OTU=');
  console.log(teachers);
  const teacherID = teachers[0].id;
  const teacher = await getTeacher(teacherID);
  const avgRating = teacher.avgRating;
  console.log(teacher);
  console.log(avgRating);

  return avgRating;
}

it returns an empty object:

actual output

dynamic graphql request vs hardcoded graphql request

i'm not sure if i'm missing something trivial, as the values being passed to searchTeacher appear to be exactly the same, but it only works when hardcoded. please let me know if i'm missing something, thank you.

CodePudding user response:

After much troubleshooting, I found the issue. @Damzaky was correct, using the localeCompare method I was able to determine that the string from the HTML and my hardcoded string were not the same, was localeCompare would return -1. I cleansed the string from the HTML using this line of code:

const normalizedName = name.normalize('NFKD');

and passed that to searchTeacher, and now the behaviour is as expected. Thanks to everyone that helped.

CodePudding user response:

It looks like an async error to me. Your async function getAvgRating is being called before the property of professorName is defined.

Try using a setTimeout in your getTeacher function.

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

  • Related