Задать вопрос
  • Почему код выполняется асинхронно?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вот здесь вы вешаете слушателя события. И он сидит себе и ждет:
    oReq.addEventListener("load", reqListener);
    Дальше вы инициируете вызов - это как ввести адрес сайта в браузере и нажать ввод. Но интернет медленный, сайт тормозной. Пройдет какое-то время.

    И вот, наконец, когда страница соизволит загрузиться, выстрелит событие "load", которое и будет отловлено слушателем - выполнится, наконец-то, функция reqListener()

    Разрыв, рвущий нить выполнения этого кода и делающий его из синхронного асинхронным – где-то внутри объекта XMLHttpRequest и не виден невооруженным глазом.

    Теоретически, внутри мог бы быть и синхронный код, который по методу send() сразу же явно дергал функцию, которую мы передали как слушателя события. Но это был бы уже не тот XMLHttpRequest, каким мы его любим.
    Ответ написан
  • Зачем тут apply (если и без него работает)?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Чтобы привязать намертво к функции контекст (this). Иначе он потеряется.
    Ответ написан
    1 комментарий
  • Как понять эти две стрелочные функции в then, что за синтаксис?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Про стрелочные функции вы ведь перечитали, прежде, чем задавать вопрос?

    () => this.setState({
      signed: true,
      isLoading: false
    }
    // то же самое, что
    var that = this;
    function() {
      that.setState({
        signed: true,
        isLoading: false
      };
    }
    Ответ написан
  • Как при помощи JS cделать?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Возможно, задача покажется проще, если из первых двух массивов сделать "словари", где ключи id, а значения name.

    Второй массив задаёт строки таблицы, первый – столбцы. Вложенный цикл.
    Ответ написан
    Комментировать
  • Как лучше всего передавать и хранить, просмотры и лайки на PHP?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Посты лайкаются и смотрятся неравномерно: бурлят свежие посты, статично висят старые-забытые.
    Поэтому для кипящего ядра можно держать данные в оперативке, скажем, в Redis – туда писать, оттуда читать. Если ключа поста нет в Redis, то вынимать из БД. Периодически из Redis'а копировать в БД все данные и убирать из Redis данные по постам, которые перестали обновляться.

    Часть нагрузки можно передать на клиент. При загрузке с сервера всем раздавать одинаковые данные о свежих постах (их id без содержания, если длинные). Далее по мере просмотра счётчики лайков/просмотров обновлять на клиенте, синхронизируя лайки с сервером не так часто. И скрипт на клиенте решает дальше, какие посты подгружать и показывать, учитывая локальные просмотры.

    Ещё мысль: nginx умеет Lua. Можно операции с лайками/просмотрами поручить сольному nginx без PHP. Правда, возникает вопрос с авторизацией.
    Ответ написан
    2 комментария
  • Как в ffmpeg из нескольких изображений и их зум склеить видео?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Всё описанное можно сделать в ffmpeg.

    Анимированный зум делается фильтром zoompan. Он с только целыми координатами работает, поэтому, чтобы не дергался, делать это в повышенном разрешении. Потом даунсэмплить.

    Например, из недавнего проекта, где интерактивно генерилась анимация по шаблону, это из bash-скрипта:
    FILTER="[0]                                                   \
        pad=color=0x99999900:w=${wIn}:h=${hIn}:x=${xPad}:y=${yPad}, \
        scale=20064x3264,                                           \
        zoompan=                                                    \
          s=${wSrc}x${hSrc}                                         \
          :d=${frames}                                              \
          :z='( ${zoomcode} ) / 16.89999'                           \
          :x='2*(${xPad} + ${xPoi}) * (zoom - 1) / zoom'            \
          :y='2*(${yPad} + ${yPoi}) * (zoom - 1) / zoom'            \
          [fg];                                                     \
          [1][fg]overlay=x=247:y=438                                \
      "

    Т.к. зумить меньше, чем влезает во вьюпорт нельзя, сначала картинке добавляется по краям паддинг прозрачный, чтобы можно было уменьшать. Потом размер увеличивается с запасом раз в 5-10, чтобы сделать незаметными целочисленные пиксельные шаги зума и смещения.
    Ответ написан
    Комментировать
  • Можно ли этот пример упростить до одного регулярного выражения?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Регулярные выражения «под капотом» не так легки, как выглядят. Там те же циклы, память.

    Данную задачу можно решить посимвольным чтением с занесением открывающих скобок в буфер FILO (First In - Last Out, Первым вошёл, последним вышел). И изъятием из буфера, с хвоста, закрывающих. До первой ошибки или до конца строки. В любой момент открывающая скобка ОК, пушится в буфер. Закрывающая ОК только, если соотв. ей открывающая – последняя в буфере. И в конце убедиться, что буфер пуст - каждой открытой нашлась пара.

    Решение, тесты проходит
    function verify(text) {
      const buffer = [];
      const valid = '()[]{}';
    
      for (let i = 0, len = text.length; i < len; i++) {
        const c = text[i];
        const idx = valid.indexOf(c);
        if (-1 === idx) continue; // не скобка
        if (idx & 1) { // закрывающая (нечет)
          if (0 === buffer.length) return false;
          if (valid.indexOf(buffer.pop()) + 1 !== idx) return false;
        } else { // открывающая
          buffer.push(c);
        }
      }
      
      return buffer.length === 0;  
    }

    Тесты
    (()=>{
    const tests = [
      ["a(b)", true         ],
      ["[{}]", true         ],
      ["[(]", false         ],
      ["}{", false          ],
      ["z([{}-()]{a})", true],
      ["", true             ],
      ["(((}", false        ],
    ];
    
    return JSON.stringify(
      tests.map(t => (verify(t[0]) === t[1] ? 'OK' : 'FAIL' ) + ': ' + t[0])
      , null,  
      2
    );
    })()
    
    
    /*
    [
      "OK: a(b)",
      "OK: [{}]",
      "OK: [(]",
      "OK: }{",
      "OK: z([{}-()]{a})",
      "OK: ",
      "OK: (((}"
    ]
    */
    Ответ написан
  • Как правильно выводить шаблон js через цикл?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    1. в приведённом фрагменте отсутствует метод appendChild(), упомянутый в ошибке.
    2. innerText это не метод, а свойство.
    3. чтобы в цикле не перезаписывались, а накапливались элементы, надо складывать.

    .then(function(result) {
      const el = document.querySelector('.response');
      let html = ''; // здесь соберём html всех блоков из цикла
      for(let i = 0, len = result.data.length; i < len; i++){
        const data = result.data[i];
        html += ` ... <img src="${data.logo}"> ... `;
      }
      el.innerHTML = html;
    })
    Ответ написан
    2 комментария
  • Как правильно добавить токен в Fetch Api?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Документация по fetch и Headers

    Рабочий код в браузере требует same origin
    const token = 'xxxxxx';
    var myHeaders = new Headers();
    myHeaders.append('x-access-token', token);
    
    var myInit = { method: 'GET',
                   headers: myHeaders,
                   mode: 'cors',
                   cache: 'default' };
    
    var myRequest = new Request('http://api.travelpayouts.com/v2/prices/latest', myInit);
    
    fetch(myRequest)
      .then(res => res.json())
      .then(data => console.log(data))
    Но в вашем случае ничего не получится из-за требования Same Origin: через JS в браузере что-то загружать с того сайта можно только страницам, загруженным с него же. Гуглите CORS. Или работайте через nodejs.

    Рабочий код под nodejs
    const http = require("http");
    
    const token = '321d6a221f8926b5ec41ae89a3b2ae7b';
    const url = 'http://api.travelpayouts.com/v2/prices/latest';
    
    http.get(
      url,
      {
          headers: {
          'x-access-token': token
          }
      },
      (res) => {
        const { statusCode } = res;
        const contentType = res.headers['content-type'];
      
        let error;
        if (statusCode !== 200) {
          error = new Error('Request Failed.\n' +
                            `Status Code: ${statusCode}`);
        } else if (!/^application\/json/.test(contentType)) {
          error = new Error('Invalid content-type.\n' +
                            `Expected application/json but received ${contentType}`);
        }
        if (error) {
          console.error(error.message);
          // Consume response data to free up memory
          res.resume();
          return;
        }
      
        res.setEncoding('utf8');
        let rawData = '';
        res.on('data', (chunk) => { rawData += chunk; });
        res.on('end', () => {
          try {
            console.log("raw data:", rawData);
            
            const parsedData = JSON.parse(rawData);
            console.log(parsedData);
          } catch (e) {
            console.error(e.message);
          }
        });
      }
      
    ).on('error', (e) => {
      console.error(`Got error: ${e.message}`);
    });
    Ответ написан
  • Как вывести данные из unixtime?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Unix time это целое число секунд с начала эпохи Unix, 1 января 1970.
    В JavaScript время считается не в секундах, а в миллисекундах (1/1000 секунды). Поэтому надо будет домножить на 1e3. Это время можно передать единственным параметром в конструктор объекта Date:
    var vkApiResponse = {
      "response": 1467726682
    };
    
    
    var D = new Date(vkApiResponse.response * 1000);
    D.toString() // Tue Jul 05 2016 16:51:22 GMT+0300 (Moscow Standard Time)
    Ответ написан
    Комментировать
  • Как показать ссылку только 5 пользователям за раз?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Можно сделать JS, который от каждого пользователя будет пинговать ваш сервер раз в N секунд, подтверждая, что пользователь всё ещё на сайте. Прекращение поступления пинга с id отображаемого у того пользователя баннера делает такой баннер вакантным для нового отображения.

    На бэкенде в момент загрузки страницы определяется, какой из вакантных баннеров можно показать.
    Ответ написан
  • Простейший калькулятор на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    prompt() возвращает String, который надо привести к числу.
    Условие прекращения цикла возможно, не то, что вам на деле требуется, я бы ограничил число итераций:
    var a = +prompt('summa'), i = 0;
    for ( ; ++i<5; a *= 1.012) {
      console.log(`${i}: ${a}`); // смотрим в консоль
    }
    // ввёл 200
    // получилось:
    /*
    1: 200
    2: 202.4
    3: 204.8288
    4: 207.28674560000002
    */


    Ну и вспоминаем математику. Тут идёт умножение числа a на 1.012n раз. Сразу можно посчитать как 1.012 в степени n. Обратная задача - логарифм. Например, как узнать, сколько раз надо умножить на 1.012 сумму 20, чтобы получить 30:Math.log(30/20) / Math.log(1.012) // 33.991
    Ответ написан
  • Сортировка по N значений?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    может, просто слепить значения в строку и сортировать по строке?
    $tosort = array_map(
      function($el) {
        $el['sortable'] = implode(',', [$el['sort_0'], $el['sort_1'], $el['sort_2'], $el['sort_3']]);
        return $el;
      },
      $products
    );
    
    $result = usort(
      tosort,
      function( $a, $b) {
        return $a.sortable < $b.sortable ? -1 : 1;
      }
    );


    p.s. Как «прекрасен» PHP, посмотри:

    Как раз в этом коде понадобились два метода для работы с массивами, и у одного
    array_map() аргументом сначала идёт callable, потом массив;
    а у другого
    usort() наоборот: сначала массив, потом callable.
    ¯\_(ツ)_/¯
    Ответ написан
  • Как сделать отсчет времени в PHP?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Вероятно, можно вычислять время получения очередного бонуса, или даже сколько бонусов должно быть у человека в любой момент времени.

    Например, 1 бонус полагается каждые 15 минут с момента первого визита. Надо запомнить в БД id пользователя и время его первого визита. Тогда при любом следующем его обращении к боту можно посчитать, сколько у того бонусов. Текущее время минус время 1-го визита (в сек.) разделить на 900 и взять целую часть.
    Ответ написан
    3 комментария
  • Как понять синтаксис ES6?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Стрелочные функции это лаконичная запись функций и небольшие отличия с контекстом.
    arr.filter( (num) => num > 0 && num % parseInt(num) === 0 )
    
    // то же, что
    arr.filter( function(num) { return   num > 0 && num % parseInt(num) === 0 ;}  )

    Оставляет только те элементы массива, которые больше нуля И остаток деления (%) на целое значение себя же равен нулю. Т.е. являются квадратами целого.
    Ответ написан
  • Необходим ли здесь Symbol?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Без использования символа переменная handlers имеет значение undefined, которое тоже можно использовать как свойство объекта.
    const a = {};
    let b;
    a[b] = "test";
    
    JSON.stringify(a)
    // "{\"undefined\":\"test\"}"
    
    a[undefined] // "test"
    Ответ написан
    Комментировать
  • Как вызвать код функции?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Оберните код функции и вставьте его сразу в документ, не надо AJAX:
    const mySuperAnimationFunction = () => {
    
    // тут весь "код функции"
    
    }

    И когда нужно выполнить анимацию - доскроллили до места - вызывайте её: mySuperAnimationFunction();
    Ответ написан
    Комментировать
  • Как настроить таймер на javascript - время до открытия магазина?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно всё считать в локальной временной зоне. Известно смещение от UTC времени магазина. Текущее смещение посетителя от UTC получаем через getTimezoneOffset().

    Задача получить два объекта времени: открытия и закрытия магазина, во временной зоне браузера посетителя.

    Если какой-то из двух оказался в прошлом, добавляем ему один день, чтобы оба оказались в будущем. Который из двух оказался меньше – подскажет, открыт сейчас магазин или закрыт.

    Решение
    function tillItOpens() {
      const D = new Date();
      const shopOffsetMin = 5 * 60; // GMT+5
      const myOffsetMin = D.getTimezoneOffset();
      const diffMin = shopOffsetMin + myOffsetMin;
      
    
      function futureDate(hours, fixMin) {
        const d = new Date();
        d.setHours(hours);
        d.setMinutes(0 + fixMin);
        d.setSeconds(0, 0);
        if (d < new Date()) d.setDate(d.getDate() + 1);
        return d;
      }
    
      
      const dOpens = futureDate(9, diffMin);
      const dCloses = futureDate(21, diffMin);
    
      if (dOpens < dCloses) {
        // скоро откроется
        const hours = Math.floor((dOpens - D) / 36e5);
        const minutes = Math.floor((dOpens - D) / 6e4) - 60 * hours;
        
        return `до открытия ${hours}:${minutes}`
        
      } else {
        // сейчас открыто
        return "Сейчас открыто!";
        // хорошо ещё посмотреть, сколько остаётся до закрытия - успеет ли чел.
        // ближайшее закрытие – объект dCloses
      }
    }

    Если сейчас закрыт, запускайте таймер обратного отсчёта до объекта dOpens – он означает время открытия в текущей таймзоне.
    Ответ написан
    3 комментария
  • Как написать скрипт на PHP?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    sscanf()

    $str = '921205400655';
    list($year, $month, $day) = sscanf($str, "%2d%2d%2d");
    if ($year > 30) $year = 1900 + $year;
    else $year = 2000 + $year;
    $date = sprintf("%04d.%02d.%02d", $year, $month, $day);
    
    echo $date; // 1992.12.05
    Ответ написан
    6 комментариев
  • Почему код не работает?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Пишите не через точку, а так примерно:
    json['1 Часть'].t13[0]

    См. доступ к свойствам объекта.
    Ответ написан