Может быть обещание быть сборщиком мусора слишком рано без .then () в JavaScript - PullRequest
0 голосов
/ 23 января 2019

Итак, я хочу выполнить 2 синхронных обещания. Вот так:

(function foo() {
  var newValues = ...;
  this.getMessages().then((msgs: Array<any>) => {
    this.saveMessages(msgs.concat(newValues));
  });
})()

Теперь, так как я не хочу ждать, пока saveMessages завершит выполнение, я не добавил .then() в конце. Так как мне плевать на результат. Я просто хочу, чтобы выполнялась асинхронная функция, поэтому в какой-то момент у нас есть сообщения в автономном режиме.

НО Я боюсь, что обещание может собрать мусор, поскольку по стандарту (насколько я знаю) вам всегда нужно .then для обещаний.

Таким образом, мой вопрос заключается в том, нужно ли мне добавлять пустой .then, чтобы убедиться, что это не сборщик мусора слишком рано и функция не будет работать правильно. Вот так: this.saveMessages(msgs.concat(newValues)).then();?

И это одинаково в браузере и NodeJS?

Ответы [ 4 ]

0 голосов
/ 23 января 2019

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

// This is pseudo synchronous execution of the code
function foo() {
  var newValues = 'testing';
  return this.getMessages()
  .then((msgs: Array<any>) => {
    // here return is important
    return this.saveMessages(msgs.concat(newValues));
  });
}

Вы можете уменьшить сложность, используя функцию async / await :

aync function foo() {
    try {
        var newValues = 'testing';
        const msgs = await this.getMessages()
        await this.saveMessages(msgs.concat(newValues))
    } catch (ex) {
        // handle your error here
    }
}
0 голосов
/ 23 января 2019

НО Боюсь, что обещание может собрать мусор, так как по стандарту (насколько я знаю) вам всегда нужно .then() для обещаний.

Нет.Насколько мне известно, такого стандарта не существует, в котором говорится, что ГХ освободит память, выделенную для объекта Promise, если к нему не присоединен .then().

Обещаниябудет выполняться независимо от того, присоединен ли .then() - или a .catch() в этом отношении - к нему.

Так что мой вопрос заключается в том, нужно ли мне добавить пустой .then() кубедитесь, что это не сборщик мусора слишком рано и функция не будет работать правильно.

Нет, вам не нужен пустой .then()

И это то же самоев браузере и NodeJS?

Да, если вы используете одну и ту же реализацию Promise в обеих средах выполнения.


Итак, с этим все будет в порядке:

function foo() {
  var newValues = ...;
  this.getMessages().then((msgs: Array<any>) => {
    this.saveMessages(msgs.concat(newValues));
  });
}

Но, вы должны рассмотреть возможность присоединения .catch() к нему для обработки любых ошибок.Если вы этого не сделаете, у вас будет UnhandledPromiseRejectionWarning.В будущих версиях Node это может привести к сбою всего вашего приложения.Прочитайте об этом здесь

РЕДАКТИРОВАТЬ

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

const n = 100;

const sleep = (id, seconds) =>
    new Promise(resolve => {
        setTimeout(() => {
            console.log(`promise with id ${id} is resolving`);
            resolve();
        }, seconds * 1000);
    });

for (let i = 0; i < n; i++) {
    sleep(i, 1 * i);
}

console.log("Last line of parent");
0 голосов
/ 23 января 2019

Нет, Обещание ничего не знает о том, как вы справляетесь с его завершением, пока не доберетесь до него.

Вам не нужно беспокоиться о сборке мусора превентивно, Javascript умнее этого, но вам нужно беспокоиться о глобальном контексте выполнения, завершающем, как в вашей программе, закрывающей соединение, до того, как Promiseрешено, что затем отменит обещание и выполнит сборку мусора.

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

var imDone = false;

function foo() {
  var newValues = ...;
  this.getMessages().then((msgs: Array<any>) => {
    this.saveMessages(msgs.concat(newValues))
         .catch(err=> { console.log(err); imDone = true; })
         .then(()=> imDone = true);                           
  }).catch(err=> console.log(err));
}

....

if (imDone) {
  // finish execution, res.send() or res.end() in Node
} 
0 голосов
/ 23 января 2019

вы можете использовать этот код и вернуть ваше первое обещание, а второе обещание - выполнить синхронизацию.

function foo() {
  var newValues = ...;
  return this.getMessages().then((msgs: Array<any>) => {
    this.saveMessages(msgs.concat(newValues));
  });
}
...