добавить задержку (синхронную) для работы с современными браузерами, кроме IE

#javascript #jquery #asynchronous #settimeout #q

#javascript #jquery #асинхронный #settimeout #q

Вопрос:

Рабочий код: в Chrome, Firefox

 let sleep = function (ms) {
   return new Promise(resolve => setTimeout(resolve, ms))
};
  

И где-то в моей функции я использую async,await, чтобы сделать задержку синхронной

 function updateHandler(newTags, tagName, contentIds) {
    let deferred = Q.defer(),
        counter = 0,
        failedIDS = [],
        data = {};
    data["contentIds"] = contentIds;
    data["failedIDS"] = failedIDS;
    if (contentIds.length === 0) {
        return Promise.resolve(data);
    }
     //aync and await is here
    _.forEach(contentIds, async function (contentId) {
        //wait for some time and continue
        await sleep(150);

        let tags = [], activity;

        //API hits..
        osapi.jive.core.get({
            v: "v3",
            href: "/contents/"   contentId   ""
        }).execute(function (content) {
            tags = content.tags;
            activity = content["updated"];
            content["tags"] = _.union(tags, newTags);
            osapi.jive.core.put({
                v: "v3",
                href: "/contents/"   contentId   "",
                body: content,
                "minor": "true",
                "updated": activity
            }).execute(function (response) {
                    counter  ;
                    if (response.error) {
                        failedIDS.push(contentId);
                    }
                    if (counter === contentIds.length) {
                        deferred.resolve(data);
                    }
                }, function (error) {
                    counter  ;
                    failedIDS.push(contentId);
                    if (counter === contentIds.length) {
                        deferred.resolve(data);
                    }
                }
            );
        })
    });
    return deferred.promise;
};
  

Таким образом, для того, чтобы этот API-интерфейс заработал и обновил все элементы, необходимо 0,15 секунды.

Поскольку async и await не будут работать в IE, я хотел написать базовую wait(ms) функцию, которая ожидает 0,15 секунды.

Примечание: Итак, без sleep() функции приведенный выше цикл отлично работает для первой итерации и завершается сбоем для второй итерации и завершает выполнение кода. ТАКИМ образом, для каждой итерации требуется задержка в 0,15 секунды, это ограничение продукта.

setTimeout() является асинхронным.. поэтому я его не использовал.

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

 function wait(ms) {
  console.log("started............");
    var start = Date.now(),
        now = start;
    while (now - start < ms) {
      now = Date.now();
    }
  console.log("finished............");
}
  

Вопрос: Я хочу иметь задержку не менее 0,15 секунды для каждой итерации, как я могу этого добиться.

Я попробовал следующий способ, изображение здесь. Успешно обновляет только от 16 до 19 содержимого из 100 повторяющихся элементов, а затем выдает то же самое, error что и без sleep() функции. введите описание изображения здесь

Комментарии:

1. Почему бы просто не использовать setTimeout с вашим дальнейшим кодом в обратном вызове?

2. Я пробовал это, если повторяющиеся элементы равны 100, то он обновляется для диапазона от 16 до 19, а затем выдает ту же ошибку (которую я получал при запуске без sleep() )

3. Как насчет определения массива с вашими элементами, а затем установки таймаута для функции, в которой первый элемент будет передан вашему api. После этого функция установит для себя еще один тайм-аут

4. @gopigorantala Вы можете прочитать эту статью mozilla

5. Вы пробовали рекурсивный setTimeout? Это должно гарантировать задержку между каждым последующим запросом

Ответ №1:

Допустим, мне нужно запускать эту функцию запроса каждые 150 мс:

 const request = () => new Promise(res => setTimeout(() => { console.log('done'); res() }, 1000))
//
  

Затем я могу использовать setTimeout рекурсивно для добавления задержки между каждым запросом:

 let counter = 0;

// this handler will be passed into a setTimeout
// to kick off the whole thing
const handler = () => {
  console.log(counter);

  // request api thing
  request().then(() => {
    counter  ;
    if (counter === 100) return;
    setTimeout(handler, 150) // remove this
  })
}

// kick off
setTimeout(handler, 150)
  

Это гарантирует, что каждый запрос завершен, прежде чем ожидать запуска следующего.

Комментарии:

1. У меня есть рекурсивный вызов функции, например: updateHandler(a,b,c).then(...) и в then() я проверяю, есть ли failedIds .. и если они !=0 , то вызываю тот же рекурсивный fn. Позвольте мне попробовать ваш подход в рамках итерации и выполнить обещание..

2. Спасибо .. это решение сработало для меня .. хотя мне нужно сделать обещание совместимым с IE

3. <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.5/bluebird.min.js"></script> добавление этого заставило обещание сработать как по волшебству..

4. рад, что это помогает. В прошлом мне приходилось разрабатывать для ie11 несколько раз и заполнять. ввод-вывод — это божья милость!

5. поскольку каждый promise разрешен.. Я установил время ожидания равным 0 вместо 150 миллионов .. это более оптимизировано с точки зрения производительности.. будьте осторожны, установка 0 также добавляет некоторую задержку setTimeout на 16-20 миллиметров.. ссылка: цикл обработки событий (потрясающе объяснено ..) .. посмотрите это видео до конца, станет понятнее, как цикл обработки событий работает в однопоточной среде (JS).