@fraps01

Как запомнить текст, который выполняется в функции?

var request = require("request");
function more() {
var url = "...";  //... - сайт, к которому выполняется реквест
request(url, function(error, response, body) { 
return body; // body - текст, который выводит сайт
});
};

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

more()[0];
Сначала он выполнит реквест, потом выведет результат

Этого можно как-то избежать? К этой функции нужно обращаться только один раз в день, в остальные случае обращаемся только к переменной.
  • Вопрос задан
  • 170 просмотров
Решения вопроса 1
lastuniverse
@lastuniverse
Всегда вокруг да около IT тем
Основная проблема в получении body заключена в том, что request асинхронный. То есть ответ придет не сразу, а через какое то время, при этом, js не будет дожидаться этого ответа а продолжит выполнять код, находящийся после request-а. Это в свою очередь приведет к тому, что в этом коде мы не можем получить ответ request-а, так происходит потому, что ответ еще не пришел)
Как же быть в этой ситуации???
Почитать про ассинхронность, промисы и async/await

Далее привожу простенький класс, умеющий кэшировать ответы requesta, и пример его использования:
тык сюда

var request = require("request");


// создаем класс для кэширования результатов запросов
class СacheRequest {
	// конструктор
	constructor(handler){
		// создаем ассоциативный массив для кэширования результата
		this.cache = {};
	}
	
	// основной метод класса, предназначен для получения данных по ссылке
	// принимает url в качестве параметра
	// возвращает выполненный промис если запрос есть в кэше
	// или промис в ожидании выполнения запроса
	async get(url){
		// если такой запрос уже был, возвращаем промис с результатом из кэша
		if( this.cache[url] )
			return  Promise.resolve(this.cache[url]);
		
		// иначе возвращаем промис с ожиданием результата
		return new Promise((resolve,reject)=>{
			// делаем запрос на указаный url
			request(url, (error, response, body)=>{
				// если ошибка - реджектим )
				if( error )
					return reject(error);
				
				// иначе запоминаем в кэше ответ
				this.cache[url] = body;

				// и резолвим body
				resolve(body);
			});			
		});
	}

	// метод отчищает кэш
	clear(){
		this.cache = {};
	}
}

// создаем экземпляр кэша
const cacheRequest = new СacheRequest();

// так как request асинхронный, то для того, чтобы получить 
// результат запроса в "синхронном стиле" используем await

// await можно использовать только внутри асинхронной функции.
// для этой цели обернем блок с вызовами cacheRequest.get в
// само вызывающуюся асинхронную функцию
(async () => {
	// выполняем запросы:
	// запросим "http://google.ru/" (будет сделан фактический запрос)
	let body = await cacheRequest.get("http://google.ru/");
	console.log("\n\n\nBODY:", body, 111);

	// еще раз запросим "http://google.ru/" (будет взято из кэша)
	body = await cacheRequest.get("http://google.ru/");
	console.log("\n\n\nBODY:", body, 222);
})()

// раз в сутки отчищаем кэш
setTimeout(()=>{
	cacheRequest.clear();
}, 1000*60*60*24 ); // 1000*60*60*24 это количество миллисекунд в сутках

Ответ написан
Пригласить эксперта
Ответы на вопрос 1
TTATPuOT
@TTATPuOT
https://code.patriotovsky.ru/
Переменную за границами функции объявите. Пример реализации:
let exemple;

const updateExempleValue = () => {
    if (exemple === undefined) { //Если переменная undefined то в любом случае стучимся к серверу
        exemple = 'ok'; //Здесь ваша фукцния по заданию переменной, вмето 'ok'.
    }
    return exemple; //Возвращаем переменную
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы