После передачи «данных» на стороне сервера клиенту я не могу сохранить «данные» в переменной и получить неопределенное значение.
Почему это происходит и как я могу решить эту проблему?
Запрос делается на стороне клиента:
(function () {
var M;
var url = '/app/get/metafield';
fetch(url)
.then((response) => response.json())
.then(function (data) {
filter(data)
});
function filter(data) {
console.info('data :', data) // 25
M = JSON.stringify(data);
}
console.info('M :', M) // undefined
});
Это код на стороне сервера:
app.get('/app/get/metafield', function (req, res, next) {
function (error, response, body) {
var data = JSON.parse(body)
var M = data.metafields[0].value;
return res.json(M);
})
});
Вместо этого вы должны попытаться запустить console.info в блоке .then()
. Это связано с тем, что http-запросы являются асинхронными операциями, поэтому в приведенном выше блоке кода строка с console.info('M :', M)
будет выполнена до того, как запрос будет завершен и возвращен.
Поэтому вам следует добавить оператор console.info()
в определенную вами функцию фильтра, чтобы console.info()
выполнялся после выполнения обещания.
fetch(url)
.then((response) => response.json())
.then(function (data) {
filter(data);
console.info(data);
});
function filter(data) {
console.info('data :', data) // 25
M = JSON.stringify(data);
console.info('M :', M)
}
Спасибо за помощь.
Проблема здесь в том, что вызов fetch
имеет значение асинхронный, что означает, что вы не будете точно знать, когда он завершится. Вместо этого, если вам нужны какие-либо данные, которые зависят от результата вызова fetch
, вы должны связать их с обратным вызовом.
Вы можете думать об этом так:
Я говорю своему другу перейти fetch
по URL-адресу, но вместо того, чтобы ждать, пока он закончит, я даю ему инструкции (обратный вызов) о том, что делать, когда он закончит, а затем тем временем я могу поработать над чем-то другим. Инструкции также содержат доступ к переменной M
, которую он должен обновить, когда закончит.
Я не знаю, когда он закончит, поэтому я не могу полагаться на ценность M
как извлеченных данных для всего, что я хочу сделать. Поэтому, если я хочу что-то, что зависит от извлеченных данных, я должен включить это в инструкции.
Решение состоит в том, чтобы присоединить еще один обратный вызов к цепочке промисов. Вы можете сделать это в стиле функционального программирования:
fetch(url)
.then((response) => response.json())
.then(filter)
.then(process);
function filter(data) {
console.info('data :', data) // 25
return JSON.stringify(data);
}
function process(data) {
...
}
Вы можете прочитать больше о цепочке промисов здесь:
NB: как правило, не рекомендуется использовать глобальные переменные для сильно асинхронного кода. Вы уже поняли причину; трудно понять, когда для переменной будет установлено какое значение, потому что нет никаких гарантий относительно порядка выполнения асинхронных функций. Лучший способ — передать данные, которые вам нужно использовать, как я сделал выше с process(data)
. Это называется функцией pure
, потому что никакие переменные вне функции не затрагиваются, все, что она делает, это берет входные параметры и преобразует их в возвращаемое значение.
Спасибо, Майк. Это действительно прояснило ситуацию.
Хотя мой вопрос похож на вопрос, который вы опубликовали, я чувствую, что он отличается, поскольку я спрашивал больше о сохранении информации и ее глобальном вызове / о том, как область будет работать с fetch();