首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StackExchange测验

StackExchange测验
EN

Code Review用户
提问于 2018-06-09 16:42:18
回答 1查看 97关注 0票数 3

我做了一个小测验,在那里你会得到一个随机的问题,你必须猜测它来自哪个StackExchange站点。

代码语言:javascript
复制
const optionsCount = 6;
const sitesURL = 'https://api.stackexchange.com/2.2/sites?pagesize=999&filter=!SmNU3t0u7kg0gEzR5B';
const questionsURL = 'https://api.stackexchange.com/2.2/questions?page=1&pagesize=100&order=desc&sort=votes&filter=!bA1d_Kvv2YPQWk';

let game = {
  questionReady: false,
  question: {},
  options: [],
  answer: 0,
  questionsAnswered: 0,
  questionsCorrect: 0,
  sites: []
}

let elements = {
  stats: null,
  question: null,
  options: [],
  next: null
}

document.addEventListener('DOMContentLoaded', init);

function init() {
  elements.stats = document.getElementById('stats');
  elements.question = document.getElementById('question');
  elements.next = document.getElementById('next');
  
  let answers = document.getElementById('answers');
  for(let i = 0; i < optionsCount; i++) {
    let button = document.createElement('button');
    button.addEventListener('click', makeGuess.bind(null, i));
    answers.appendChild(button);
    elements.options.push(button);
  }
  
  loadSites().then(chooseQuestion);
}

function loadSites() {
  return fetch(sitesURL)
    .then(response => response.json())
    .then(data => {
      game.sites = data.items.filter(e => e.site_type === "main_site");
    })
}

function loadQuestions(index) {
  return fetch(questionsURL + '&site=' + game.sites[index].api_site_parameter)
    .then(response => response.json())
    .then(data => {
      game.sites[index].questions = data.items;
    })
}

async function chooseQuestion() {
  game.options = getOptions(optionsCount, game.sites.length);
  game.answer = randInt(optionsCount);
  game.question = await getQuestion(game.options[game.answer]);
  updateView();
  game.questionReady = true;
}

function getOptions(amount, max) {
  let options = [];
  while(options.length < amount) {
    let value = randInt(max);
    if(!options.includes(value)) {
      options.push(value);
    }
  }
  return options;
}

function randInt(limit) {
  return Math.floor(Math.random() * limit);
}

async function getQuestion(index) {
  if(!game.sites[index].questions) {
    await loadQuestions(index);
  }
  let size = game.sites[index].questions.length;
  return game.sites[index].questions[randInt(size)];
}

function updateView() {
  elements.question.innerHTML = game.question.title;
  for(let i = 0; i < optionsCount; i++) {
    elements.options[i].innerHTML = game.sites[game.options[i]].name;
  }
}

function makeGuess(guess) {
  if(game.questionReady) {
    game.questionsAnswered++;
    if(guess === game.answer) {
      game.questionsCorrect++;
    }
    else {
      elements.options[guess].classList.add('wrong');
    }
    elements.options[game.answer].classList.add('correct');
    elements.next.disabled = false;
    elements.question.setAttribute('href', game.question.link);
    let percent = Math.round(100 * game.questionsCorrect / game.questionsAnswered);
    elements.stats.innerText = `${game.questionsCorrect}/${game.questionsAnswered} - ${percent}%`;
    game.questionReady = false;
  }
}

function onNextClick() {
  elements.question.removeAttribute('href');
  for(option of elements.options) {
    option.classList.remove('correct', 'wrong');
  }
  elements.next.disabled = true;
  chooseQuestion();
}
代码语言:javascript
复制
.correct {
  background-color: #54da54;
}
.wrong {
  background-color: #ff6565;
}
#answers button {
  margin: 2px;
}
代码语言:javascript
复制
0/0 - 0%





Next question

如果你喜欢摆弄的话,这里有一个JSFiddle

它应该能在所有的现代浏览器中工作。我尝试在可能的情况下利用一些新的javaScript特性。我想知道我是否能使代码更好,比如使用最佳实践、可读性、效率等等。

EN

回答 1

Code Review用户

回答已采纳

发布于 2018-06-09 20:25:42

下面是一些关于我注意到的一些事情的快速评论。

码样式

考虑将代码包装在立即调用的函数表达式中。这将防止页面上的其他代码(意外)与您的代码交互。

在下面的循环中,您将在全局命名空间中删除option。使用const option of elements.options代替:

代码语言:javascript
复制
  for(option of elements.options) {
    option.classList.remove('correct', 'wrong');
  }

考虑更多地使用const。如果您不打算重新赋值一个变量,声明它const将提醒您您正在做一些您在过去不打算做的事情。它还可能提高性能。

错误处理

您的代码缺少错误处理。特别是,如果api调用失败,您的代码将在let size = game.sites[index].questions.length;行上失败。抓住错误并相应地做些事情。

onclick

不要在html元素上使用onclick或其任何兄弟节点作为属性。(实际上,也不要在javascript中使用它),请使用addEventListener,就像您已经为其他按钮所做的那样。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/196170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档