Использование async / await для последовательного (блокирования вызовов) возврата слишком рано - PullRequest
0 голосов
/ 24 мая 2018

Ниже приведен простой пример, демонстрирующий, почему я пытаюсь использовать API выборки.Я надеюсь, что async fetchAsync () будет блокировать до тех пор, пока он не вернет данные (или исключение), но вывод показывает, что это не так.

constructor entering fetchAsync... ** we are here!!! ** leaving fetchAsync. finish initialization

Я пытался выяснить,Как отобразить завершающую строку (we are here) после finish initialization, когда мой объект завершает инициализацию с содержимым файла.Разве ожидание / асинхронность не должны блокировать, пока это не будет сделано?

class A {
    filename = "./resources/test.json";

    constructor() {
        console.log("constructor");
        this.fetchAsync(this.filename)
            .then( data => this.initialize(data)
            ).catch(reason => console.log(reason.message))
    }

    async fetchAsync(filename) {
        console.log("entering fetchAsync...");
        let data = await (await fetch(filename)).json();
        console.log("leaving fetchAsync.");
        return data;
    }

    initialize() {
        setTimeout(() => console.log("finish initialization"), 1000)
    }
}

let a = new A();
console.log("*** we are here!!! ***");

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы должны забыть, что означает asyn хронический:

class A {
  constructor() {
      this.filename = "./resources/test.json";
      console.log("constructor");
      this.fetchAsync(this.filename)
          .then( data => this.initialize(data)
          ).catch(reason => console.log(reason.message))
  }

  async fetchAsync(filename){
      console.log("entering fetchAsync...");
      let data = await fetch(filename);
      console.log("leaving fetchAsync.");
      return data.json;
  }
  initialize() {
      setTimeout(() => {console.log("finish initialization"); console.log("*** we are here!!! ***"}, 1000)
  }
}
let a = new A();
0 голосов
/ 24 мая 2018

await не блокирует - это было бы очень неудобно для пользователя и приложения - оно просто ждет выполнения обещания, прежде чем продолжить, и не может быть выполнено на верхнем уровне (пока).Если вы хотите, чтобы we are here отображался только после завершения инициализации, вам нужно иметь доступ к обещанию, которое разрешается после завершения инициализации, а затем вызывать then для него.

Вы также должны убедиться, чтоinitalize возвращает Обещание, чтобы его можно было связать с внешним вызовом на a.

Итак, вы можете попробовать что-то вроде этого:

const dummyRequest = () => new Promise(res => setTimeout(res, 1000, 'response'));

class A {
  // filename = "./resources/test.json";
  constructor() {
    console.log("constructor");
  }
  startFetch() {
    return this.fetchAsync(this.filename || 'foo')
      .then(data => this.initialize(data)).catch(reason => console.log(reason.message))
  }
  async fetchAsync(filename) {
    console.log("entering fetchAsync...");
    // let data = await (await fetch(filename)).json();
    const data = await dummyRequest();
    console.log("leaving fetchAsync.");
    return data;
  }

  initialize() {
    return new Promise(resolve => {
      setTimeout(() => {
        console.log("finish initialization");
        resolve();
      }, 1000);
    });
  }
}

const a = new A();
a.startFetch()
  .then(() => {
    console.log("*** we are here!!! ***");
  });

Конструкторы не могут быть асинхронными, поэтому я сделал функцию startFetch.

...