Programer Beginner
Programer Beginner

Reputation: 1429

Change Typescript Function to retrieve JSON data from Session Storage instead of a JSON file

Context

I have the following typescript code from mkdocs-material's bundle.ts:

/**
 * Fetch search index
 *
 * @returns Search index observable
 */
function fetchSearchIndex(): Observable<SearchIndex> {
  if (location.protocol === "file:") {
    return watchScript(
      `${new URL("search/search_index.js", config.base)}`
    )
      .pipe(
        // @ts-ignore - @todo fix typings
        map(() => __index),
        shareReplay(1)
      )
  } else {
    return requestJSON<SearchIndex>(
      new URL("search/search_index.json", config.base)
    )
  }
}

The SearchIndex interface looks like so (located at src/assets/.../config/index.ts:

export interface SearchIndex {
  config: SearchConfig
  docs: SearchDocument[]
  options: SearchOptions
}

The JSON data in the search_index.json has the following structure:

{
  "config": {
    "lang": [
      "en"
    ],
    "separator": "[\\s\\-]+",
    "pipeline": [
      "stopWordFilter"
    ]
  },
  "docs": [
    {
      "location": "some-location-text",
      "title": "some-title-text",
      "text": "some-text-text"
    },
    {
      "location": "some-location-text",
      "title": "some-title-text",
      "text": "some-text-text"
    }
  ]
}

Question

How can I modify the fetchSearchIndex() function so that instead of retrieving/observing the JSON data from the search_index.json file, it will retrieve the JSON data from the session storage (under the key search-index)?

My Attempt

Do note that I am a Python programmer and not fluent in TypeScript/JavaScript at all. Despite that, here was my attempt:

function getFromSessionStorage(key: string): Observable<string> {
  return new Observable<string>((observer) => {
    try {
      const value = sessionStorage.getItem(key);
      if (value === null) {
        observer.error(new Error('Key not found in sessionStorage'));
      } else {
        observer.next(value);
        observer.complete();
      }
    } catch (error) {
      observer.error(error);
    }
  });
}

function fetchSearchIndex(): Observable<SearchIndex> {
  const searchIndex = sessionStorage.getItem('search-index');
  if (searchIndex ) {
    return getFromSessionStorage('search-index')
      .pipe(
        map(x => JSON.parse(x)),
        shareReplay(1)
      )
  } else {
    // original fetchSearchIndex() code here
  }
}

Unfortunately, that did not work as I got the following error:

index.ts:99 Uncaught (in promise) TypeError: r.location.split is not a function or its return value is not iterable
    at ne (index.ts:99:33)
    at new H (index.ts:146:16)
    at index.ts:152:15
    at Generator.next (<anonymous>)
    at s (search.dfff1995.min.js:1:966)

Upvotes: 0

Views: 67

Answers (1)

Programer Beginner
Programer Beginner

Reputation: 1429

The issue was unrelated to the code that I provided and my code was indeed behaving correctly as it should. The issue was the content of the search-index retrieved from the sessionStorage was an incorrect JSON.

After fixing the content of the sessionStorage, everything works as it should.

Upvotes: 0

Related Questions