DEV Community

artydev
artydev

Posted on

Asynchronous pagination using generators 1/2

For documentation about generators look here Generators

Here is a way to accomplish asynchrounous paging using generators


const data = [...Array(400)].map((_,i) => `${i + 1}`);
const itemsPerPage = 10;
const next = "next";
const prev = "prev";
const forward = 1;
const backward = -1;
const nbPages =  Math.ceil(data.length/itemsPerPage) ;
const click = "click";

let pagination;
let currentPage = 1;

const delay = (ms) => {
  return new Promise ((res, err) => {
    setTimeout(res, ms) 
  })
}

async function fetchData (start, end) {
  await delay(0)
  return await  data.slice(start, end);
}

async function* paginate(data, itemsPerPage) {
    let index = 0;
    const stepindex = (dir) => index += dir * itemsPerPage;
    while (true) {
        const direction = yield ;
        if (direction === next) {
            stepindex(forward);
        } else if (direction === prev) {
            stepindex(backward);
        }
        yield await fetchData(index, index + itemsPerPage);
    }
}

async function nextItems () {
  let res = (await pagination.next(next)).value; 
  pagination.next()
  return res;
}  

async function prevtItems () {
  let res =  (await pagination.next(prev)).value;
  pagination.next()
  return res;  
}   

function limitSup () {
  return currentPage == nbPages;
}

function limitInf () {
  return currentPage == 1;
}

function renderView (pageItems) {
  if (typeof(pageItems) != typeof([]))  { 
    alert("too fast")
    return;
  }
  page.innerText = `${currentPage}/${nbPages}`
  results.innerHTML = `
    <table border='0' width="20%">
      <tr><td>Items nĀ°</td><td>value</td></tr>
      ${pageItems.map(it => `
        <tr>
          <td style='padding:1rem'>${it}</td>
          <td>data-${it}</td>
        </tr>`).join('')} 
    </table>
  ` 
}

document.getElementById(next).addEventListener(click, async () => {
  if (limitSup()) return;
  currentPage = Math.min(++currentPage, nbPages)
  renderView (await nextItems())
})

document.getElementById(prev).addEventListener(click, async () => {
  if (limitInf ()) return;
  currentPage = Math.max(--currentPage, 1)
  renderView (await prevtItems())
})


function main () {
  renderView(data.slice(0, itemsPerPage))
  pagination = paginate(data, itemsPerPage);
  pagination.next();
}

main ()

Enter fullscreen mode Exit fullscreen mode

You can play with the demo here Demo

Top comments (0)