Как получить только последний ответ от функции async / await - PullRequest
1 голос
/ 03 марта 2020

Как игнорировать все старые вызываемые async/await функции, если вызывается несколько асинхронных / ожидающих функций.

Например, это мой пример.

let isLoading = false;

const onResponse = dateTime => {
  console.log(dateTime);
  isLoading = false;
}

const asyncFunction = async () => {
  await delay(1000);
  return new Date();
}

Теперь, например, если Я вызывал функцию asyncFunction 3 раза в течение 1 секунды, затем я возьму onResponse 3 раза, и моя переменная isLoading будет работать неправильно.

function loadData() {
  isLoading = true;
  asyncFunction.then(onResponse);
}

Как я могу получить ответ только от последнего вызова и игнорировать все ранее другие.

Ответы [ 6 ]

3 голосов
/ 03 марта 2020

Я бы просто сохранял какое-то значение и увеличивал его каждый раз, когда вы вызываете вашу асин c функцию. Затем в обработчике вы можете проверить, не изменилось ли это значение. Если нет, просто вернитесь - это значит, что потом был еще один звонок.

1 голос
/ 03 марта 2020

вот реализация Робо Робок ответ (если вы проголосуете за меня, тоже проголосуйте за него)

let isLoading = false;
let promiseCounter = 0;

const delay = time => new Promise(res => setTimeout(() => {res()}, time))

// use a destructuring assignement
const onResponse = ({dateTime, promiseId}) => {
  // refuse promise if it was not the last
  if (promiseId !== promiseCounter) {return;}
  // reset counter to avoir overflow on really long run
  promiseCounter = 0;
  
  // do what needs to be done
  console.log("onResponse", dateTime);
  isLoading = false;
}

const asyncFunction = async () => {
  const promiseId = ++promiseCounter;
  await delay(1000);
  return {dateTime: new Date(), promiseId};
}

function loadData() {
  isLoading = true;
  asyncFunction().then(onResponse);
}

(async ()=>{
  // simulate multiple calls with a total interval > delay of one resposne
  console.log("first call at", new Date())
  loadData()
  for (let i = 0; i < 100; i++) {
    await delay(30);
    loadData()
  }
  console.log("last call at", new Date())
})()

do c: деструктурирующее назначение

1 голос
/ 03 марта 2020

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

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

const onResponse = dateTime => {
  console.log(dateTime);
}

const asyncFunction = async () => {
  await setTimeout(() => {}, 1000);
  return new Date();
}

function debounce (callback, delay) {
    let timeout;

    return function (then) {
        const that = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => callback.apply(that, []).then(then), delay);
    };
}

const debouncedFunction = debounce(asyncFunction, 100);

debouncedFunction(onResponse);
debouncedFunction(onResponse);
debouncedFunction(onResponse);
debouncedFunction(onResponse);

enter image description here

1 голос
/ 03 марта 2020

Если вы хотите, чтобы только последний завершенный результат работал примерно так:

let finalResult;

const workFunc = async () => {
   finalResult = new Date();
}

await Promise.all([ workFunc(), workFunc(), workFunc() ]);

console.log(finalResult);
0 голосов
/ 06 мая 2020

В следующем коде определяется функция latest, которая может быть применена к функции, чтобы обеспечить выполнение только последнего вызова до завершения.

Переменная curr записывает последний вызов, сохраняя последнее обещание , Функция сконфигурирована в позиции then для обеспечения продолжения. Прогресс в цепочке обещаний разрешается только в том случае, если обещание в процессе выполнения равно curr. ie. последующий вызов не перезаписал curr за это время.

Таким образом, распечатывается следующий код: stale two.

function latest(fn) {
    let curr = null
    return (...args) => {
        let p = fn(...args).then((result) =>  { 
            if(p === curr) return result
            else throw 'stale' 
        })
        curr = p
        return p
    }
}

const doSomething = (v, ms) => new Promise((r)=> setTimeout(() => r(v), ms))
const latestDoSomething = latest(doSomething)

latestDoSomething('one', 100).then(console.log).catch(console.log)
latestDoSomething('two', 100).then(console.log).catch(console.log)
0 голосов
/ 03 марта 2020

Вы можете использовать Promise.All:

await Promise.all([Call1(), Call2(), Call3(),...]).then(values => { 
  //values is [value1,value2,....,lastValue]
  console.log(values[values.length-1]); last value is in the last entry
});
...