JavaScript - запуск только одного промиса для нескольких запросов

Я хочу, чтобы объекты запрашивали обещание JavaScript, но я не хочу, чтобы они создавали отдельные обещания. Логика, которой я хочу добиться, следующая — проверить, ожидает ли промис, и только если нет, создать новый промис. Это возможно? Согласно документации, я не могу проверить статус промиса, я могу обрабатывать его только после его выполнения, но я не хочу вызывать обработчики для каждого запроса промиса, и я не хочу запускать несколько промисов, если обратный вызов одного промиса может ответ на все прошлые просьбы...

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


person qiubit    schedule 14.11.2015    source источник
comment
Если вы более подробно описываете РЕАЛЬНУЮ проблему, которую пытаетесь решить (включая код для ваших двух операций), а не описываете свою попытку собственного решения (см. Проблема XY), мы можем показать вам, как правильно использовать промисы для ее решения.   -  person jfriend00    schedule 14.11.2015
comment
@ jfriend00 есть много вариантов использования, когда этот шаблон применяется и не является проблемой XY: например, несколько битов кода выполняют один и тот же запрос, и вы не хотите запускать новый запрос для каждого, но также не хотите для кэширования значений, поскольку они могут измениться.   -  person Benjamin Gruenbaum    schedule 14.11.2015
comment
@BenjaminGruenbaum - Вы догадались, чего хочет ОП, и можете предложить только общее решение своей догадки. Если OP предоставляет свою реальную проблему и примеры своего фактического кода, нам не нужно точно угадывать, что они пытаются сделать, и мы можем дать гораздо более конкретный ответ. Я советую ОП о том, как сделать их вопрос намного лучше, который потребует гораздо более конкретного ответа и не предполагает догадок, чего они хотят. Возможно, вы догадались правильно, я действительно не уверен. Но любой вопрос, требующий угадывания, может быть лучше.   -  person jfriend00    schedule 14.11.2015
comment
Итак, вам просто нужен кеш с использованием промиса? Итак, первый, кто запрашивает данные, создает фактический запрос, а все остальные просто используют тот же результат?   -  person jfriend00    schedule 14.11.2015
comment
Да, это именно то, что я хотел :)   -  person qiubit    schedule 14.11.2015
comment
Вы хотите, чтобы кеш сохранялся, чтобы будущие запросы использовали предыдущий результат?   -  person jfriend00    schedule 14.11.2015
comment
Нет, на самом деле это было сделано только для предотвращения ненужных выборок JSON, но этот JSON содержит временные данные, поэтому будущий запрос (который ДЕЙСТВИТЕЛЬНО не близок к другому запросу) должен снова получить JSON.   -  person qiubit    schedule 14.11.2015
comment
Это похоже на дубликат кэширования результатов обещания JavaScript   -  person Bergi    schedule 14.11.2015


Ответы (1)


Конечно, это довольно легко сделать

var _p = null; // just a cache
function batchRequests(fn){
    if(_p != null) return _p; // if we have an in-flight request, return it
    _p = fn(); // otherwise start a new action
    _p.then(function(){ _p = null; },  // delete cache on resolve
            function(){ _p = null; }); // even on failure
    return _p; // return the new in-flight request
}

Что позволяет вам делать:

function delay(){ // just for example, simulate a request
    return new Promise(function(resolve){ setTimeout(resolve, 1000); });
}

var batched = function(){ return batchRequests(delay); };
batched().then(function(){ console.log("All these"); });
batched().then(function(){ console.log("execute after"); });      
batched().then(function(){ console.log("one second, at the same time"); });
person Benjamin Gruenbaum    schedule 14.11.2015
comment
Может ли многопоточность быть проблемой? (Извините, если это глупый вопрос, я новичок в JavaScript и не знаю, как работают эти асинхронные функции, но теоретически у нас может быть несколько потоков в пакетных запросах, они проверяют, что в глобальной переменной нет промиса, а затем каждый тред дает свое обещание...) - person qiubit; 14.11.2015
comment
Вкратце - нет. В глубине - вероятно, нет, если только вы не используете его в Rhino или как встроенный язык в другом языке и не наследуете проблемы многопоточности из этой среды. Таким образом, нет применимо к большинству сред (браузер, узел и т. д.). - person Benjamin Gruenbaum; 14.11.2015
comment
@jamesemanon batchRequests принимает функцию в качестве параметра и возвращает функцию, которая действует как функция ввода, за исключением того, что она демонстрирует поведение, запрошенное OP. Обещание представляет собой ценность + время, а не действие. Обещание похоже на уже начатую операцию. Если бы batchRequests вернул обещание, было бы невозможно получить поведение OP только для пакетной обработки до разрешения, о котором запросил OP. - person Benjamin Gruenbaum; 14.11.2015
comment
Я копаю, но я прогнал его через Babel, и он выдал ошибку с ошибкой типа. Любопытный. Я перепроверю то, что у меня есть, возможно, я ошибаюсь. - person james emanon; 14.11.2015