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

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

从 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");

为 HTML 分页创建的构造函数,它还从 Array:movieInfo 中呈现数据,以创建各自的电影卡片,这些卡片主要显示电影名称、图像和描述。现在我想让这个构造函数异步并且只在 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;
})();

使您的 IIFE 成为命名函数声明(下面的init())。并执行该函数作为 async Promise 决议的回调。

注意:您应该用 try/catch 块包围对 async 函数的调用。

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

popularMovies().then(init);

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