Обещание 2 разрешается до обещания 1 - PullRequest
0 голосов
/ 08 февраля 2019

Я выполняю поиск в текстовом поле, и когда я набираю текст, происходит вызов, идущий на сервер после, скажем, 100 мс.

Например, если мы ищем «5041» и сразу ищем «50»и снова сделайте его "5041", тогда к бэкэнду будет сделано 3 вызова.

1."5041" -> Promise 1

2."50"   -> Promise 2

3."5041" -> Promise 3

Однако обещание 3 (веб-вызов занимает 200 мс) разрешается до того, как обещание 2 (веб-вызов занимает 500 мс), которое делаетна экране отображаются результаты для обещания 2 («50»), когда все, что у меня есть в текстовом поле, - «5041».

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

Этого можно добиться, используя switchMap из rxjs в угловом приложении.Однако мне нужен способ добиться того же в ванильном JS.

Ответы [ 3 ]

0 голосов
/ 10 февраля 2019

Сначала вы можете заключить вашу функцию fetchData в нечто вроде fetchLatestSearchResults function , которая отмечает время, когда был сделан сетевой вызов , и возвращает самый последний результат из всех сетевых вызовов * 1006.* (независимо от того, какие данные были возвращены с сервера)

const generateLatestSearchFetch = function(fetchFunc){
  let mostRecentResult = null;
  let mostRecentResultFetchTime = Date.now();

  return (...args) => {

    const myFetchStartTime = Date.now();

    return fetchFunc(...args)
      .then(data => {
        if (myFetchStartTime > mostRecentResultFetchTime) {
          mostRecentResult = data;
          mostRecentResultFetchTime = myFetchStartTime
        }
        return mostRecentResult;  
      });
  }
};

Используйте Like :

fetchData = generateLatestSearchFetch(fetchData);
fetchData('10'); // resolves first and returns result for 10
fetchData('102'); // resolves third and returns result for 1024
fetchData('1024'); // resolves second and returns result for 1024

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

0 голосов
/ 15 февраля 2019

Для этого вы можете использовать шаблон наблюдателя.

const createWrapper = (fn) => {
    let counter = 0;
    let lastFetchId = 0;
    const listeners = [];
    return {
        fetch: (str) => {
            let id = ++counter;
            fn(str).then((data) => {
                if(id > lastFetchId) {
                    listeners.forEach(fn => {
                        fn(data);
                    });
                    lastFetchId = id;
                }
            });
        },
        listen: (fn) => {
            listeners.push(fn);
            return () => {
                const index = listeners.indexOf(fn);
                listeners.splice(index, 1);
            };
        }
    }
}

const SearchWrapper = createWrapper(fetchData);

SearchWrapper.fetch('a');
SearchWrapper.fetch('b');
SearchWrapper.fetch('c');

SearchWrapper.listen((data) => {
    console.log(data);
})
0 голосов
/ 08 февраля 2019

Вам нужна «последняя» функция:

// takes a function returning a promise and only reports the last resort
function last(fn) { 
  let p;
  return function(...args) {
    let current = fn(); // call the function
    p = current; // mark it as the last call
    return p.then(result => { 
      // ask am I still the last call?
      if (p === current) return result;
      else return new Promise(() => {}); // never resolve
    });
  }
}

let onlyLastSearch = last((name) => fetch('/api?name=' + name));

onlyLastSearch('a'); // will be ignored
onlyLastSearch('b'); // will be ignored
onlyLastSearch('c'); // only relevant result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...