Оператор Fortran SAVE

Данные загружаются из Firestore асинхронно. Остальная часть вашего кода продолжает выполняться, пока загружаются данные, и затем ваш обратный вызов then вызывается, как только данные появляются.

Проще всего это увидеть с помощью нескольких правильно расположенных операторов журнала:

console.log("Starting to load data");
docRef.get().then(function (doc) {
  console.log("Got data");
});
console.log("Started to load data");

Когда вы запускаете это, он печатает:

Начало загрузки данных [ 1126]

Начата загрузка данных

Получены данные

blockquote>

Вероятно, это не тот результат, который вы ожидали, но он полностью объясняет поведение, которое вы видите. Прямо сейчас ваш return store запускает перед store = doc.data(), что объясняет, почему вы не получаете желаемый результат.


Это означает, что любой код, которому нужны данные, должен находиться внутри обратного вызова then(). Поэтому, если вы переместите вызов на setState() сразу после store = doc.data(), он будет работать:

docRef.get().then(function (doc) {
  if (doc.exists) {
    store = doc.data();
    this.setState({name: store});
  } else {
    // doc.data() will be undefined in this case
    console.log("No such document!");
  }
})

В качестве альтернативы, вы можете вернуть значение из then() вверх. В этом случае вам также понадобится then() в вашем коде вызова:

function collectres () {
  var docRef = db.collection("cities").doc("SF");
  return docRef.get()
    .then(function (doc) {
      if (doc.exists) {
        return doc.data();
      } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
      }
    })
    .catch(function (error) {
      console.log("Error getting document:", error);
    });
}

И затем вызовите его с помощью:

Random() {
    let a = '';
    user.collectres().then(function(a) {
      this.setState({name:a});
    });
}

Асинхронные API чрезвычайно распространены в Современное программирование, поэтому я настоятельно рекомендую прочитать их. Для получения дополнительной информации см .:

38
задан High Performance Mark 15 August 2018 в 08:18
поделиться

3 ответа

В принципе, когда модуль выходит из области видимости, переменные этого модуля становятся неопределенными - если они не объявлены с атрибутом SAVE или не используется инструкция SAVE. «Не определено» означает, что вы не можете полагаться на переменную, имеющую предыдущее значение, если вы снова используете модуль - он может иметь прежнее значение при повторном доступе к модулю, или он может не иметь - нет гарантии , Но многие компиляторы не делают этого для переменных module - переменные, вероятно, сохраняют свои значения - компилятору не стоит пытаться выяснить, остается ли модуль в области действия или нет, и, вероятно, переменные модуля рассматриваются как глобальные переменные - но не полагайтесь на это! Чтобы быть в безопасности, либо используйте «сохранить», либо «используйте» модуль из основной программы, чтобы он никогда не выходил за рамки.

«save» также важно в процедурах, чтобы сохранить «state» между вызовами подпрограммы или функции (как написано @ire_and_curses) - инициализациями «first invocation», счетчиками и т. Д.

subroutine my_sub (y)

integer :: var
integer, save :: counter = 0
logical, save :: FirstCall = .TRUE.

counter = counter + 1

write (*, *) counter

if (FirstCall) then
   FirstCall = .FALSE.
   ....
end if

var = ....

и т. Д.

В этом фрагменте кода «counter» сообщит о количестве вызовов подпрограммы x. Хотя на самом деле в Fortran> = 90 можно пропустить «save», потому что инициализация в объявлении подразумевает «save».

В отличие от случая модуля, в современных компиляторах без атрибута save или объявления инициализации по объявлению локальные переменные процедур обычно теряют свои значения при вызовах. Поэтому, если вы попытаетесь использовать «var» в последующем вызове, прежде чем переопределять его в этом вызове, значение будет неопределенным и, вероятно, не будет значением, рассчитанным при предыдущем вызове процедуры.

Это отличается от поведения многих компиляторов FORTRAN 77, некоторые из которых сохранили значения всех локальных переменных, хотя это не требовалось языковым стандартом. Некоторые старые программы были написаны с учетом этого нестандартного поведения - эти программы не будут работать на новых компиляторах. Многие компиляторы имеют возможность использовать нестандартное поведение и «сохранять» все локальные переменные.

LATER EDIT: обновление с примером кода, который показывает некорректное использование локальной переменной, которая должна иметь атрибут сохранения, но не имеет:

module subs

contains

subroutine asub (i, control)

   implicit none

   integer, intent (in) :: i
   logical, intent (in) :: control

   integer, save :: j = 0
   integer :: k

   j = j + i
   if ( control ) k = 0
   k = k + i

   write (*, *) 'i, j, k=', i, j, k

end subroutine asub

end module subs

program test_saves

   use subs
   implicit none

   call asub ( 3, .TRUE. )
   call asub ( 4, .FALSE. )

end program test_saves

Локальная переменная k подпрограммы преднамеренно неправильно используется - в этой программе она инициализируется при первом вызове, поскольку control равен TRUE, но при втором вызове control равен FALSE, поэтому k не переопределено. Но без атрибута save k не определено, поэтому использование его значения недопустимо.

Скомпилировав программу с помощью gfortran, я обнаружил, что k все равно сохранил свое значение:

 i, j, k=           3           3           3
 i, j, k=           4           7           7

Скомпилировав программу с опциями ifort и агрессивной оптимизации, k потерял свое значение:

 i, j, k=           3           3           3
 i, j, k=           4           7           4

При использовании ifort с опциями отладки проблемы были обнаружены во время выполнения!

 i, j, k=           3           3           3
forrtl: severe (193): Run-Time Check Failure. The variable 'subs_mp_asub_$K' is being used without being defined
47
ответ дан M. S. B. 27 November 2019 в 03:47
поделиться

Краткое объяснение может быть следующим: атрибут save говорит, что значение переменной должно сохраняться при разных вызовах одной и той же подпрограммы / функции. В противном случае обычно, когда вы возвращаетесь из подпрограммы / функции, «локальные» переменные теряют свои значения, так как память, в которой хранились эти переменные, освобождается. Это как static в Си, если вы знаете этот язык.

2
ответ дан ShinTakezou 27 November 2019 в 03:47
поделиться

Обычно локальные переменные выходят из области видимости после того, как выполнение завершает текущую процедуру, и поэтому не имеют «памяти» своего значения при предыдущих вызовах. SAVE - это способ указать, что переменная в процедуре должна сохранять свое значение от одного вызова до следующего. Это полезно, когда вы хотите сохранить состояние в процедуре, например, чтобы сохранить текущую сумму или сохранить конфигурацию переменной.

Здесь есть хорошее объяснение с примером.

4
ответ дан 27 November 2019 в 03:47
поделиться
Другие вопросы по тегам:

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