简体   繁体   English

使构造函数异步并且仅在将 API 中的所有数据检索到数组中时才被调用

[英]To make a Constructor Asynchronous and only be called once all the data from the API is retrieved into the Array

Data fetched from the API stored in the Array: movieInfo从存储在数组中的 API 获取的数据:movieInfo

let movieInfo = [];

async function popularMovies() {
  let page = 1;

  let lastResult = [];

  do {
    try {
      const resp = await fetch(popularAPIURL + `&page=${page}`);
      const data = await resp.json();
      lastResult = data.total_pages;
      data.results.forEach((result) => {
        movieInfo.push(result);
      });
      page++;
    } catch (err) {
      console.error(`Oops, Something is wrong ${err}`);
    }
  } while (lastResult);

  console.log(movieInfo);
}

console.time("Time my API Call");
popularMovies();
console.timeEnd("Time my API Call");

Constructor function created for HTML pagination which also renders data from the Array: movieInfo to create respective Movie cards which basically displays the movie name, image and descp.为 HTML 分页创建的构造函数 function 还呈现来自 Array:movieInfo 的数据以创建相应的电影卡,这些卡基本上显示电影名称、图像和 decp。 Now I want to make this Constructor Asynchronous and only be called once the Array: MovieInfo has retrieved all the data from the API现在我想让这个构造函数异步并且只有在 Array: MovieInfo 从 API 检索到所有数据后才被调用

class Paginator {
  constructor(totalRecords, recordsPerPage = 1, visiblePages = 1) {
    this.recordsPerPage = recordsPerPage;
    this.totalRecords = totalRecords;
    this.noOfPages = Math.ceil(this.totalRecords / this.recordsPerPage);
    this.visiblePages = visiblePages;
    this.activePage = 1;
    this.visiblePagesEndRange = visiblePages;

    this.validate();
  }

  validate() {
    if (this.recordsPerPage <= 0) {
      this.recordsPerPage = 1;
    }
    if (this.visiblePages <= 0) {
      this.visiblePages = 1;
    }
    if (this.totalRecords <= 0) {
      this.totalRecords = 1;
    }
    if (this.noOfPages <= 0) {
      this.noOfPages = Math.ceil(this.totalRecords / this.recordsPerPage);
    }
    if (this.visiblePagesEndRange <= 0) {
      this.visiblePagesEndRange = this.visiblePages;
    }
    if (this.visiblePages > this.noOfPages) {
      this.visiblePages = this.noOfPages;
      this.visiblePagesEndRange = this.visiblePages;
    }
    if (this.recordsPerPage > this.totalRecords) {
      this.recordsPerPage = this.totalRecords;
    }
  }

  gotoNextPage() {
    if (this.activePage < this.noOfPages) {
      this.activePage += 1;

      if (this.activePage > this.visiblePagesEndRange) {
        this.visiblePagesEndRange += this.visiblePages;
        this.visiblePagesEndRange = Math.min(
          this.visiblePagesEndRange,
          this.noOfPages
        );
      }
    }
  }

  gotoPrevPage() {
    if (this.activePage > 1) {
      this.activePage -= 1;
      if (this.activePage % this.visiblePages === 0) {
        this.visiblePagesEndRange = this.activePage;
      }
    }
  }

  gotoFirstPage() {
    this.activePage = 1;
    this.visiblePagesEndRange = this.visiblePages;
  }

  gotoLastPage() {
    this.activePage = this.noOfPages;
    this.visiblePagesEndRange = this.noOfPages;
  }

  gotoPage(page) {
    this.activePage = page;
  }

  getVisiblePagesRange() {
    let beginningVisiblePage;
    let endingVisiblePage;
    //  When the visiblepagesendrange % visiblepages is not zero (which means that all the pages cannot be fit in the visible pages range) and if our ending page range is equal to total no pages then the beginning would be equivalent to visble page range - ((visible page range mod visiblepage range) - 1) i.e the leftover pages until the end.
    if (
      this.visiblePagesEndRange % this.visiblePages !== 0 &&
      this.visiblePagesEndRange === this.noOfPages
    ) {
      beginningVisiblePage =
        this.visiblePagesEndRange -
        ((this.visiblePagesEndRange % this.visiblePages) - 1);
    }
    // else we are always in a place where, current visible page end range - visible page range + 1 will return us the correct beginning position for the page range.
    else {
      beginningVisiblePage = this.visiblePagesEndRange - this.visiblePages + 1;
    }
    //Also endingActivePage would be simply equal visiblePagesEndRange.
    endingVisiblePage = this.visiblePagesEndRange;
    return {
      beginningVisiblePage,
      endingVisiblePage,
    };
  }

  getActivePageIndices() {
    // the beginning page index will be current active page multiplied by no of records.
    let beginningPageIndex = (this.activePage - 1) * this.recordsPerPage;
    // the ending page index will be minimum of total records and (beginning + records allowed per page);
    let endingPageIndex = Math.min(
      beginningPageIndex + this.recordsPerPage,
      this.totalRecords
    );
    return { beginningPageIndex, endingPageIndex };
  }
}

// All the render and using Paginator class logic comes here
(function () {
  function nextPage() {
    paginator.gotoNextPage();
    render();
  }

  function prevPage() {
    paginator.gotoPrevPage();
    render();
  }

  function lastPage() {
    paginator.gotoLastPage();
    render();
  }

  function firstPage() {
    paginator.gotoFirstPage();
    render();
  }

  // Delegating event to the parent ul.
  function gotoPage(event) {
    if (event.target.nodeName === "BUTTON") {
      const page = parseInt(event.target.dataset.item);
      paginator.gotoPage(page);
      render();
    }
  }

  const paginationPages = document.querySelector(".pagination__pages");

  paginationPages.addEventListener("click", gotoPage);

  //  paginator object
  // list which is of length 346
  // recordsPerPage = 6
  // visiblePages = 6

  const paginator = new Paginator(movieInfo.length, 20, 6);

  // Method to render the pagination buttons;
  function renderPages() {
    const paginationPages = document.querySelector(".pagination__pages");
    let html = "";
    let { beginningVisiblePage, endingVisiblePage } =
      paginator.getVisiblePagesRange();
    for (let page = beginningVisiblePage; page <= endingVisiblePage; page++) {
      const pageClass =
        paginator.activePage === page
          ? "pagination__page-btn--active"
          : "pagination__page-btn";
      html += `<li class='pagination__page'>
   <button data-item=${page} class=${pageClass}>${page}</button>
     </li>`;
    }
    paginationPages.innerHTML = html;
  }

  // Method to render the list items
  function renderList() {
    // const list = document.querySelector(".list");
    const mainContent = document.getElementById("main-content");
    const { beginningPageIndex, endingPageIndex } =
      paginator.getActivePageIndices();
    let html = "";
    for (let index = beginningPageIndex; index < endingPageIndex; index++) {
      // html += `<li class='list__item'>${records[index]}</li>`;
      html = `<div class="container">
      <div class="card">
        <figure class="card__thumb">
          <img src= "${IMG_URL + movieInfo[index].poster_path}"/>
          <figcaption class="card__caption">
            <h2 class="card__title">${movieInfo[index].name}</h2>
            <p class="card__snippet">${movieInfo[index].overview}</p>
            <a href="" class="card__button">Read more</a>
          </figcaption>
        </figure>
      </div>
    </div>`;
    }
    mainContent.innerHTML += html;
  }

  // Main render function
  function render() {
    renderPages();
    renderList();
  }

  render();

  this.firstPage = firstPage;
  this.lastPage = lastPage;
  this.nextPage = nextPage;
  this.prevPage = prevPage;
  this.gotoPage = gotoPage;
})();

Make your IIFE a named function declaration ( init() below).将您的 IIFE 命名为 function 声明(下面的init() )。 And execute that function as a callback for your async Promise resolution.并执行 function 作为async Promise 分辨率的回调。

NOTE: you should surround your call to your async function with a try/catch block.注意:你应该用try/catch块包围你对async function 的调用。

async function popularMovies() {
  //...
  return movieInfo;
}

popularMovies().then(init);

// Replace your IIFE with this
function init(movieInfo) {
  //...
  const paginator = new Paginator(movieInfo.length, 20, 6);
  //...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM