[Игра с Наггетс] Кто мои лайки и мои 💗, ты здесь?

Node.js внешний интерфейс JavaScript
[Игра с Наггетс] Кто мои лайки и мои 💗, ты здесь?

Это 18-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления.

предисловие

Играть в Наггетссерия, расширяющая некоторые интересные функции для Nuggets, такие как:

Однажды, зайдя на свою личную домашнюю страницу, я увидел, что она мне уже понравилась другим.Да, я бросаю Бога.
Как новички, это нормально поддерживать друг друга Кому эти 💗 мои даны, добивайтесь реального образа и реализуйте его сами.

Демонстрация эффекта

Подробный список можно щелкнуть, чтобы перейти на страницу статьи.
stars.gif

Адрес источника

Адрес источника:JJMyStarAndC

Серверная служба написана на nodejs, и вам необходимо установить соответствующий установочный пакет.

Реализовать идеи

Возможные идеи:

  1. Плагин Chrome + скрипт обезьяны
  2. Статические страницы + прокси nginx
  3. Статическая страница + переадресация услуги
  4. ......

Идея этой статьи заключается в静态页面 + nodejs自定义服务,
Просто дополнительно для удовольствияServer Sent Events, называемая SSE, односторонняя отправка на стороне сервера,Его функция заключается в том, что после того, как сервер получит данные, он в одностороннем порядке отправляет их в службу поддержки клиентов.

Некоторые люди могут сказать, почему бы и нетsocket.io, позвольте мне сказать кое-что здесь,socket.ioТак называемый jQuery в сокете, все понимают, что это значит, и его нужно использовать вместе с его серверной библиотекой, ненавижу его! !

Лучшее решение: прозрачная передача
express + http-proxy-middleware

детали реализации

сбор информации

Все крутится вокруг данных, если данных нет, не надо делать торты и говорить об идеалах.

Для приобретения Звезды достаточно одного интерфейса!

Адрес запроса: API.Nuggets.Talent/interact_AP…
Метод запроса: post
Параметры запроса:
Это скрытоlimitКак насчет вариантов параметров? Каждый может попробовать!

 {
    cursor: `${cursor}`,  // 起始查询位置
    item_type: 2,    // 文章点赞,对应有沸点点赞
    sort_type: 2,   // 排序,有近导员
    user_id: uid, // 用户id
  }

Возвращаемый результат:

{
   has_more: true,
   data: [{
       author_user_info:{
           user_id: "3465271329953806", // 用户ID
           user_name: "小魔童哪吒" // 用户名
       }, 
       article_info: {
           article_id: "6996484371305725965"  // 文章ID
           title: "k8s 学习二"  // 文章标题
       }
   }]
}

при запросе,cursorОчень важный параметр, указывающий положение указателя, откуда продолжать идти назад.
В возвращаемом результате очень важные поляhas_more, указывает на то, что данных еще нет, если они есть, продолжайте сбор.

В самородках очень много интерфейсов, и ограничений поначалу не было, в начале помню, что некоторые интерфейсы можно передать.limitПараметр 1000, тоже нормально, позже его доработали, что достойно похвалы.

Его цикл получает основной код:

 while (res.has_more) {
    data.cursor = `${cursor}`
    
    res = (await axios.default.post(url, data, {
      headers
    })).data;
    
    cursor += 10;
    await delay(undefined, 16).run();  // 暂停16ms, 故意的
  }

Мы сказали, что вот данные, полученные сервером, но они не были переданы во внешний интерфейс.

передача данных

Использовать SSE на стороне nodejs тоже очень просто, здесь я не буду использовать стороннюю библиотеку.

  1. запрос прошел uid, избавился от двух параметров uid означает идентификатор пользователя, rid означает requestId
  2. getStarsУказывает на запуск запроса
  3. Суть SSE заключается вContent-Typeа такжеConnection
    'Content-Type': 'text/event-stream'Тип объявления
    'Connection': 'keep-alive'Указывает, что соединение не закрыто
  4. Поскольку это тоже запрос, мы используем центр событий для отправки событий в запрос, а запрос записывает обратно данные
app.get('/sseStream', function (request, response) {
  response.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  const { uid, rid } = request.query;
  console.log("uid:", uid);

  // 查询用户的点赞
  getStars(uid, rid);

  // 产线可别这么用
  eventsCenter.removeAllListeners("ssePush");
  // 事件中心
  eventsCenter.on("ssePush", function (event, data) {
    // console.log("push message to clients");
    response.write("event: " + String(event) + "\n" + "data: " + JSON.stringify(data) + "\n\n");

  });
});

Куда отправляется событие, то есть куда отправляется сбор данных, добавлю код, тут еще два событияmessageTotal, messageEnd, одно — это общее сообщение, а другое — это сообщение, указывающее на завершение запроса.

async function getStars(uid, rid) {
  let cursor = 0
  const data = {
    cursor: `${cursor}`,
    item_type: 2,
    sort_type: 2,
    user_id: uid,
  }
  let res = {
    has_more: true
  };

  while (res.has_more) {
    data.cursor = `${cursor}`

    res = (await axios.default.post(url, data, {
      headers
    })).data;

    console.log("res:", data, res)

    eventsCenter.emit("ssePush", "messageTotal", {
      uid,
      rid,
      count: res.count
    });
    eventsCenter.emit("ssePush", "message", {
      uid,
      rid,
      datas: (res.data || []).map(d => ({
        user_id: d.author_user_info.user_id,
        user_name: d.author_user_info.user_name,
        title: d.article_info.title
      }))
    });
    cursor += 10;
    await delay(undefined, 16).run();
  }
  eventsCenter.emit("ssePush", "messageEnd", {
    uid,
    rid
  })
}

Сбор данных переднего плана

Передний план соответствует событию мониторинга, это так просто.

    const source = new EventSource(`/sseStream?uid=${uid}&rid=${rid}`);

    // 收到新数据
    source.addEventListener('message', function (e) {
        let data = JSON.parse(e.data)
        // 不是需要的数据
        if (data.uid != uid || data.rid != rid) {
            return;
        }

        listArr.push(...data.datas);
        // console.log("listArr:", listArr);
        renderList(listArr);
        gotStarsEl.innerHTML = listArr.length;

    }, false)

    // 收到总数据消息
    source.addEventListener('messageTotal', function (e) {
        let data = JSON.parse(e.data)

        // 不是需要的数据
        if (data.uid != uid || data.rid != rid) {
            return;
        }
        totalStarsEl.innerHTML = data.count;
    }, false)

    // 统计完毕
    source.addEventListener('messageEnd', function (e) {
        let data = JSON.parse(e.data)
        console.log("meesage", data);
    }, false)

Статистика и группировка

  1. Статистика: взять в качестве ключа ID пользователя, если нет, то создать новый, а если да, то изменить кардинальность.
  2. Сопоставьте ключи с массивом, а затем отсортируйте.

Это так просто!

    const statObj = list.reduce((obj, cur) => {
        if (hasOwnProperty.call(obj, cur.user_id)) {
            obj[cur.user_id].count += 1;
            obj[cur.user_id].items.push(cur);
        } else {
            obj[cur.user_id] = {
                items: [cur],
                count: 1,
                ...cur
            };
        }
        return obj;
    }, {});

    // 分组
    const groupList = Object
        .keys(statObj)
        .map(k => statObj[k])  //分组
        .sort((a, b) => a.count > b.count ? -1 : 1);  // 排序

Для получения дополнительных сведений о реализации перейдите к исходному коду.

напиши в конце

3-5 минут, 500-1000 слов, есть что набрать, но не слишком много хлопот.Если вы считаете, что это хорошо, то ваши лайки и комментарии - самая большая мотивация для меня двигаться дальше.

Пожалуйста, посетите группу технического обменаиди сюда. Или добавьте мое облако похорон WeChat и учитесь вместе.