I wrote the below answer for the following question on SO a couple of days ago, and I was curious if the usage of the generator function is an acceptable one.

I choose the generator function, because I could easily exchange the generator at a later time to ask the question not in sequence, but rather randomized, or whatever algorithm I might come up with at that time :)

One thing I am not entirely fond of is the restart functionality. I guess it might be better to have the logic for restarting the questionaire rather implemented inside the onCompleted callback I have now, rather than as part of the "official" end of the questionaire.

Because of this, I am now reusing an already called callback, so I guess these are things that can be improved.

Still I am curious of having a review of the usage of the generator here, and the potential overlooked drawbacks (the fact that only next is available is not something that I find a problem, I wanted it unidirectional)

const questions = [
    question: 'What platform are you on?',
    answers: ['Stackoverflow', 'codereview'],
    correct: 1,
    points: 5
    question: 'What is the answer to everything',
    answers: [42, 'I don\'t have a clue'],
    correct: 0,
    points: 1
    question: 'How much is 7*6',
    answers: ['I am not good with maths', 42],
    correct: 1,
    points: 10

// a simple generator that is used in the questionaire
function *questionsGenerator( questions ) {
  yield* questions;

const questionaire = ( query, nextButton, target, onCompleted ) => {
  let score = 0;
  let totalScore = 0;
  let iterator = questionsGenerator( query );
  let question = null;
  let selectedAnswer = -1;
  nextButton.addEventListener('click', nextQuestion);
  function evaluateAnswer() {
    if (!question) {
      // no question yet
    if (selectedAnswer < 0) {
    totalScore += question.points;
    if (question.correct === selectedAnswer) {
      score += question.points;
  function restart() {
    btnNext.removeEventListener('click', restart);
    questionaire( query, nextButton, target, onCompleted );
    btnNext.innerHTML = 'next';
  function nextQuestion() {
    question = iterator.next();
    // this is a bit of a hack to check if we just had the last question or not
    if (question.done) {
      nextButton.removeEventListener('click', nextQuestion);
      nextButton.innerText = 'Restart';
      btnNext.addEventListener('click', restart);
      onCompleted( (score / totalScore) * 100 );
    question = question.value;
  function drawUI() {
    // disable next button
    nextButton.setAttribute('disabled', true);
    selectedAnswer = -1;
    // remove existing items
    Array.from( target.childNodes ).forEach( child => target.removeChild( child ) );
    // create new questions (if available)
    const title = document.createElement('h1');
    title.innerHTML = question.question;
    target.appendChild( title );
    question.answers.map( (answer, i) => {
      const el = document.createElement('input');
      el.type = 'radio';
      el.name = 'answer';
      el.value = i;
      el.id = 'answer' + i;
      el.addEventListener('change', () => { 
        selectedAnswer = i; 
      } );
      const label = document.createElement('label');
      label.setAttribute('for', el.id );
      label.innerHTML = answer;
      const container = document.createElement('div');
      return container;      
    } ).forEach( a => target.appendChild( a ) );

// create a questionaire and start the first question
  score => alert('You scored ' + score ) 
<div id="questionaire">
<div class="toolstrip">
<button id="btnNext" type="button">Next</button>


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.