Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как ответ сервера через fetch вернуть в виде текста в переменную?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Сетевые запросы асинхронны по своей природе: выполняются непредсказуемо долго.

    Попробуйте изменить общую логику приложения так, чтобы результат запроса, когда появится, не просто назначался в какую-то переменную, а вызывал колбэк с результатом.
    function getIndex(adr) {
      // ...
      return fetch(ajaxurl, {
        method: 'POST',
        body: formData
      }).then(resp => resp.text())
        .then(showResult)
        // парашютики не забываем:
        .catch(err => console.error(err));
    }
    
    function showResult(data) {
      console.log(data);
    }
    
    getIndex('https://ya.ru/'); // вернёт промис, ну и фиг с ним


    Либо поместите всю логику дальнейшей работы с результатом прямо в цепочку промисов:
    function getIndex(adr) {
      // ...
      return fetch(ajaxurl, {
        method: 'POST',
        body: formData
      }).then(resp => resp.text())
        .then(showResult)
        .catch(err => console.error(err));
    }
    
    getIndex('https://ya.ru/')
      .then(data => {
        document.querySelector('#output').innerText = data;
      })
      .catch(err => console.error(err));
    Ответ написан
    1 комментарий
  • В чем изьяны моего чудища?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В вашем коде не сравниваются все возможные варианты.
    Он проваливает два примера из вопроса:
    [2, -1, 2, 3, -9] = 6 (у вас получается 5)
    и [-2, -1, 1, 2] = 3 (у вас выводит 2)

    spoiler
    Предлагаю такой вариант решения. Возможно, не оптимальный. Полный перебор.

    Будем двигать «окно» по массиву, считая сумму элементов в нём. Размер окна от всего массива до окошечка размером в 1 элемент.
    Считаем сумму в начальном положении окна. Затем, двигаясь вправо, вычитаем элемент слева и прибавляем элемент справа.

    Минимально возможная сумма — ноль.
    function getMaxSubSum(arr) {
      let max = 0;
      const length = arr.length;
    
      for (let frame = length; frame > 0; frame--) {
        let sum = 0;
        for (let i = 0; i < frame; i++) sum += arr[i];
        max = Math.max(max, sum);
    
        // move frame
        for (let offset = 1; offset <= length - frame; offset++) {
          sum -= arr[offset - 1];
          sum += arr[offset + frame - 1];
          max = Math.max(max, sum);
        }
      }
    
      return max;
    }
    
    
    const tests = () => {
      [
        [[-1, 2, 3, -9], 5],
        [[2, -1, 2, 3, -9], 6],
        [[-1, 2, 3, -9, 11], 11],
        [[-2, -1, 1, 2], 3],
        [[100, -9, 2, -3, 5], 100],
        [[1, 2, 3], 6],
        [[-1, -2, -3], 0],
      ].forEach((el, i) => {
        const result = getMaxSubSum(el[0]);
        console.assert(result === el[1], "Test %d failed: [%s] %d != %d", i, el[0], result, el[1]);
      })
    }
    
    tests();
    Ответ написан
  • Почему постфиксный и префиксный инкременты выдают одно и то же значение?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Разница между ++i и i++ только в том, чему равно само это выражение:
    let i = 0;
    alert(++i); // 1 – прибавили 1 и вернули результат
    
    let j = 0;
    alert(j++); // 0 – вернём значение до, и прибавим 1
    
    // после уже всё одинаково
    console.log(i, j); // 1, 1


    Тут подробнее и лучше: Инкремент/декремент
    Ответ написан
    Комментировать
  • Почему код неработает?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    из комментов выяснилась проблема, которая была решена.

    Рекомендуемое решение:
    const results = [];
    const promises = [];
    
    for (let i = 0; i < 10; i++) {
      promises.push(
        fetch('/user', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({user: i}),
          })
          .then(response => response.json())
          .then(data => results.push(data))
          .catch(err => console.error(err))
      );
    }
    
    Promise.all(promises)
      .then(() => console.log("All 10 done!", results));
    Ответ написан
  • Как выполнять следующую функцию массива через некоторое время после предыдущей?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Для реализации задуманного нужен момент окончания работы очередной функции – чтобы от него считать 2 секунды.

    В вопросе не раскрыта природа функций в массиве: то ли они мгновенно отрабатывают, то ли занимают продолжительное время. Синхронные или асинхронные. Что эти функции возвращают: Promise, значение или ничего?

    Можно обернуть каждую в Promise с таймаутом:
    [func1, func2, func3]
      // обернуть каждую в Promise:
      .map((f) => () => new Promise((res, rej) => {
        f();
        setTimeout(res, 2000));
      })
      // и собрать цепочку из этих промисов:
      .reduce((acc, c) => acc.then(c()), Promise.resolve());


    Если эти функции асинхронные, то заменить
    -    f();
    -    setTimeout(res, 2000));
    +    f()
    +    .then(() => setTimeout(res, 2000)));
    Ответ написан
    Комментировать
  • Как оптимизировать данный код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    async componentDidMount() {
        const lastSongsResponse = await fetch("https://api.laut.fm/station/key/last_songs");
        const lastSongs = await lastSongsResponse.json();
        lastSongs.length = Math.min(7, lastSongs.length);
    
        const promises = lastSongs.map((song) => new Promise((resolve, reject) => {
            const params = {
                method  : 'album.getInfo',
                artist  : song.artist.name.replace(' & ', ', '),
                album   : song.album,
                api_key : 'apikey',
                format  : 'json',
            };
    
            const url = "https://ws.audioscrobbler.com/2.0/?" + Object.keys(params).map((key) => `${key}=${params[key]}`).join('&');
    
            const cover = await fetch(url)
                .then((response) => response.json())
                .then((songData) => songData.album.image[4]["#text"])
                .catch(err => reject(err));
    
            const date = new Date(song.started_at);
    
            const songData = {
                id1        : song.id,
                id2        : song.id + 1,
                artist     : song.artist.name,
                title      : song.title,
                cover      : cover,
                started_at : date.getHours() + ':' + date.getMinutes().toString().padStart(2, '0')
            }
            
            resolve(songData);
        }));
    
        const results = await Promise.all(promises);
    
        this.setState({ results: results })
    }
    Ответ написан
    4 комментария
  • Как работает Promise.resolve в Javascript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const deferred = () => {
      Promise.prototype.resolve = () => {}; // чтобы не было ошибок )
      return Promise.resolve("web");
    }


    «Нормальное» решение:
    // проверка
    deferred()
      .then(function(res) {
        console.log(200, res);
        return "lab";
      })
      .then(function(res) {
        console.log(100, res);
      })
      .resolve("web");
    
    // реализация
    function deferred() {
      function Box() {
        this.queue = [];
      }
    
      Box.prototype.then = function(func) {
        this.queue.push(func);
        return this;
      }
    
      Box.prototype.resolve = function(first_arg) {
        let arg = first_arg;
        while (this.queue.length)
          arg = this.queue.shift().call(this, arg);
      }
    
      return new Box;
    }
    Ответ написан
    3 комментария
  • Как заменить jquery на js при работе с динамическими элементами?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    You Might Not Need jQuery (на англ.)
    Ответ написан
    Комментировать
  • Как защитить Ajax код для "общения" с API от злоумышленников?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Никак не скрыть. Что оказывается у клиента — пиши, пропало!

    Хотите сохранить ключи от API, выполняйте запросы с вашего сервера, в клиенты отдавайте уже результат.
    Ответ написан
    Комментировать
  • Как подсчитать общее количество подписчиков из нескольких групп в ВК?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    В образовательных целях можно написать код исполняемой на стороне ВК процедуры, который получит счётчики указанных групп и сложит их. И выполнить этот код методом execute()

    Код процедуры:
    var groups = "apiclub,55293029"; // сюда подставить ваши группы
    var counts = API.groups.getById({
      group_ids: groups,
      fields: "members_count",
    })@.members_count;
    var total = 0;
    while (counts.length > 0) total = total + counts.pop();
    return total;

    Понадобится токен Сообщества - любой вашей группы.
    Полный рабочий код
    $code = <<<EOFVK
    var groups = "apiclub,55293029";
    var counts = API.groups.getById({
      group_ids: groups,
      fields: "members_count",
    })@.members_count;
    
    var total = 0;
    while (counts.length > 0) total = total + counts.pop();
    return total;
    EOFVK;
    
    // токен сообщества получить в Настройках своего сообщества, Работа с API
    // нажать кнопку Создать ключ и выбрать любую галочку.
    $token = '123123123';
    
    $method = 'execute';
    $params = [
        'access_token' => $token,
        'v' => '5.130',
    ];
    
    $post_data = [
        'code' => $code,
    ];
    
    $url = sprintf(
        'https://api.vk.com/method/%s?%s',
        $method,
        http_build_query($params)
    );
    
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $post_data,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10,
    ]);
    
    $curl_result = curl_exec($ch);
    $data = json_decode($curl_result);
    
    $count = $data->response;
    
    printf('<h2>Сейчас в группах %d участников</h2>', $count);
    Ответ написан
  • Как отложить загрузки файла?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    По клику запускать таймаут, в котором программно создавать элемент ссылки с атрибутом download и программно кликать по нему:

    Ответ написан
    Комментировать
  • Как оставить выбраным хотя бы один элемент?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    При изменении любого проверять всю коллекцию: если этот последний, выключать его нельзя:
    Ответ написан
    6 комментариев
  • Как лучше всего работать с длинными путями?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Что-то типа такого
    const appendByAttr = (title, subtitle) => jQuery(`a[title="${title}"] ~ .ammenu-submenu-container .ammenu-item.-child.-col-4 a[title="${subtitle}"] ~ ul li:last-child`)
      .append($(`a[title="${title}"] ~ .ammenu-submenu-container .ammenu-item__extra`));
    
    appendByAttr('Title 1', 'Subtitle 1');
    appendByAttr('Title 2', 'Subtitle 2');
    appendByAttr('Title 3', 'Subtitle 3');
    Ответ написан
    Комментировать
  • Как проверить элементы массива на наличия определенных элементов?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Число арабскими цифрами проверить через Number(num_string)

    Число римскими лучше проверять готовой библиотекой, например sguest/RomanJS – т.к. одного наличия правильных символов не достаточно. Римские числа можно записать разными способами:
    • заглавными IX
    • маленькими ix
    • специальными Unicode-символами: Ⅸ (это один символ)
    Правильными буквами можно записать неправильное число "IMIVIIIIIII"

    Знаки операций проще всего, там подойдёт регулярное выражение /^[\*\/\+-]$/
    Ответ написан
    Комментировать
  • Как разрезать строку от одного символа до другого?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    "23к1с2".split(/[а-яй]+/)  // [ "23", "1", "2" ]
    "23к1с2".match(/([а-яй]+)/g)  // [ "к", "с" ]


    YaParse = (str) => {
      const nums = str.split(/[а-яй]+/)  // [ "23", "1", "2" ]
      const parts = str.match(/([а-яй]+)/g)  // [ "к", "с" ]
      parts.unshift("дом");
    
      return nums.reduce((acc, c, i) => (acc[parts[i]] = c, acc), {});
    }
    
    console.log(YaParse("23к1с2")); // { "дом": "23", "к": "1", "с": "2" }
    Ответ написан
    1 комментарий
  • JS как проверить, содержит ли строка И цифры И латинские буквы?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    буква-цифра ИЛИ цифра-буква:
    /(([a-zA-Z].*\d)|(\d.*[a-zA-Z]))/

    старый ответ

    const alphanum = (str) => /\d+/.test(str) && /[a-zA-Z]+/.test(str);
    Ответ написан
    Комментировать
  • Сравнение "буквенных" и "числовых" строк. Как происходит?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Про сравнение, к сожалению, только на английском: оператор «меньше»

    • если обе части — строки, то сравниваются Unicode коды
    • иначе JS попытается привести к числу не-числовые аргументы
    • .. если при этом где-то получился NaN, вернёт false
    • .. а так сравнит как числа


    В примере в вопросе как раз обе части – строки, т.к. в кавычках.
    "a" имеет код 97
    "1" имеет код 49

    "a" больше.

    Получить код символа можно методом строки codePointAt():
    "1a".codePointAt(0) // 49 - ascii и Unicode код символа "1"
    "1a".codePointAt(1) // 97 - ascii и Unicode код символа латинской маленькой "a"

    А вот с NaN вообще беспорядок:
    123 < "Z"  // false
    123 > "Z"  // тоже false
    Ответ написан
    Комментировать
  • Как проверить наличие элементов в строке между определенными элементами?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Регулярки overkill
    const str = 'dhjsd1dl[sd]sd2sdsd';
    const [a, b, c, d] = [str.indexOf('1'), str.indexOf('['), str.indexOf(']'), str.indexOf('2')];
    if ((a < b) && (b < c) && (c < d)) {
      console.log("усё у порядке");
    }
    Ответ написан
    Комментировать
  • Как взять значение из URL и запустить отсчёт от значения этого число до 0 (c помощью JS)?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Получить из адресной строки значение параметра sec см. URL.searchParams:
    const params = (new URL(document.location)).searchParams;
    const sec = Number(params.get('sec')) || 5; // или 5 по умолчанию

    Для обратного отсчёта лучше не вычитать раз в секунду единицу из счётчика, а сразу отметить момент в будущем, до которого в любой момент времени показывать оставшиеся секунды:
    const future = new Date();
    future.setTime(future.getTime() + 1000 * sec);

    Запустите таймер раз, скажем, в 200мс, и смотрите, сколько там осталось времени до момента future.
    const update = () => {
      const diff = future.getTime() - Date.now(); // сколько осталось, в миллисекундах
      const secondsLeft = Math.round(diff / 1000); // сколько осталось секунд
      if (diff <= 0) {
        // время прошло
      } else {
        // обновить в кнопке число оставшихся секунд
        // и вызвать это обновление снова через чуть-чуть:
        setTimeout(update, 200);
      }
    }
    
    update();
    Ответ написан
    2 комментария
  • Как округлить число если есть знаки после запятой?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    (n) => Math.round(n * 1e3) / 1e3

    Проверки
    const round3 = (n) => Math.round(n * 1e3) / 1e3;
    
    const test = (n) => console.log('%08f %s', n, round3(n));
    
    test(2.0001); // 2
    test(2.001); // 2.001
    test(2.01); // 2.01
    test(2.1); // 2.1
    test(2); // 2
    Ответ написан
    1 комментарий