admin管理员组

文章数量:1403364

The following code

const endpoint = '.json';
const universities = [];

fetch(endpoint)
    .then(results => results.json())

    .then(data => universities.push(...data));

console.log(universities);

function findMatches(wordToMatch, universities) {
    return universities.filter(uni => {
        const regex = new RegExp(wordToMatch, 'gi');
        return uni.name.match(regex)
    })
}

export default findMatches;

returns the error below

'Uncaught TypeError: Cannot read property 'filter' of undefined'

I can log the data using console.log(universities). So why can't I filter through it? FYI the data is an array of objects. Any help is massivaly appreciated. Thank you.

The following code

const endpoint = 'https://raw.githubusercontent./Hipo/university-domains-list/master/world_universities_and_domains.json';
const universities = [];

fetch(endpoint)
    .then(results => results.json())

    .then(data => universities.push(...data));

console.log(universities);

function findMatches(wordToMatch, universities) {
    return universities.filter(uni => {
        const regex = new RegExp(wordToMatch, 'gi');
        return uni.name.match(regex)
    })
}

export default findMatches;

returns the error below

'Uncaught TypeError: Cannot read property 'filter' of undefined'

I can log the data using console.log(universities). So why can't I filter through it? FYI the data is an array of objects. Any help is massivaly appreciated. Thank you.

Share Improve this question asked Nov 18, 2017 at 21:42 LeafysharkLeafyshark 3952 gold badges5 silver badges11 bronze badges 9
  • 1 how are you invoking findMatches – linasmnew Commented Nov 18, 2017 at 21:45
  • I'm surprised that console.log logs anything. – Andy Commented Nov 18, 2017 at 21:48
  • Note that universities inside findMatches is different scope variable than const universities unless that is what you pass in when you call findMatches() – charlietfl Commented Nov 18, 2017 at 21:48
  • you are getting it because you are trying to filter an array which contains json data. – Harry Commented Nov 18, 2017 at 21:50
  • Sorry Linas, I am invoking it in another file. I import it into my main app file, then call it in there too. The actual file is then bundled by webpack. – Leafyshark Commented Nov 18, 2017 at 21:59
 |  Show 4 more ments

2 Answers 2

Reset to default 3

You need to remove universities as a parameter in your findMatches function because it is overriding the value of the local universities variable:

function findMatches(wordToMatch) {
    return universities.filter(uni => {
        const regex = new RegExp(wordToMatch, 'gi');
        return uni.name.match(regex)
    })
}

You can then proceed to use the findMatches function as follows:

findMatches("hi") // returns a filtered array

Edit:

You have a race condition in your code, wherein findMatches might be called before your fetch is plete. To fix the issue, findMatches should return a promise like so:

const endpoint = 'https://raw.githubusercontent./Hipo/university-domains-list/master/world_universities_and_domains.json';
const universities = [];

const promise = fetch(endpoint)
    .then(results => results.json())

    .then(data => universities.push(...data));

console.log(universities);

function findMatches(wordToMatch) {
    return promise.then(() => universities.filter(uni => {
        const regex = new RegExp(wordToMatch, 'gi');
        return uni.name.match(regex)
    }));
}

findMatches("hi").then(arr => console.log(arr));

If you're absolutely sure that findMatches will always be called after fetch is plete, you can go with the first solution. Otherwise, it is strongly remended you go with the second solution that uses promises.

I just want to let everybody know I finally got things working. I had to install babel-polyfill and babel-preset-env and add to webpack to get UglifyJS to work with async await and to optimise bundle size.

I had to use async await instead of regular promises to get the HTML to render into the DOM for some reason, not sure why. Anyway here is the code that finally worked as expected:

UniFetch.js

const endpoint = 'https://raw.githubusercontent./Hipo/university-domains-list/master/world_universities_and_domains.json';

const universities = [];

const promise = fetch(endpoint)
    .then(blob => blob.json())
    .then(data => universities.push(...data.slice(8286, 8456)));

function findMatches(wordToMatch) {
    return promise.then(() => universities.filter(uni => {
        const regex = new RegExp(wordToMatch, 'gi');
        return uni.name.match(regex)
    }));
}

async function displayMatches() {
    searchResults.innerHTML = await findMatches(this.value)
        .then(arr => arr.map(uni => {
        return `
            <li>${uni.name}</li>
        `
    }));
}

const searchInput = document.querySelector("input[name='unisearch']");
const searchResults = document.querySelector('.unisearch__results');

searchInput.addEventListener('change', displayMatches);
searchInput.addEventListener('keyup', displayMatches);

export default findMatches

App.js

import FindMatches from '../UniFetch.js'

FindMatches()

Hope this helps some people to implement a typeahead, autoplete API fetch.

本文标签: