Функция синхронизации также синхронизируется, если она выполняется в обещании? - PullRequest
4 голосов
/ 10 октября 2019

Я просто хотел узнать, является ли функция sync, выполняемая в обещании, синхронной (и замедляет другие вещи) или асинхронной, как я думаю?

Пример:

function getFileContent(filepath){
    return new Promise((resolve, reject) => {
        fs.readFileSync("asd.txt"));
    });
}

Ответы [ 3 ]

3 голосов
/ 10 октября 2019

Функции являются синхронными. Период.

То, что может быть асинхронным, - это (абстрактный) процесс / рабочий процесс.

Когда кто-то говорит, что функция является «асинхронной», на самом деле он означает, что результат будет доступен через некоторое время. ,Результат обернут в Обещание, которое является ручкой для ожидания. Но процесс все еще может быть синхронным. Посмотрите на этот пример:

function foo() {
    return new Promise((res, rej) => {
        console.log(1);
        console.log(2);
        res();
    });
};

function test() {
    foo();
    console.log(3);
};

и результат всегда один и тот же:

> test();
1
2
3

, что означает, что каждая функция была вызвана одна за другой синхронно. И действительно, если вы обновите функцию foo до:

function foo() {
    return new Promise((res, rej) => {
        while (true) {}
        res();
    });
};

, вы заметите, что console.log(3) никогда не запускается. И поэтому наши foo блоки навсегда!

Теперь взгляните на этот пример:

function test() {
    Promise.resolve().then(function() {
        console.log(1);
        console.log(2);
    });
    console.log(3);
};

и обратите внимание на другой результат: 3 1 2. Все эти функции синхронны , так почему порядок отличается? Потому что .then() откладывает выполнение на некоторое более позднее время.

В общем: sync / async на самом деле не свойство функции, а скорее свойство рабочего процесса. И в вашем случае это синхронно.

Примечание: это усложняется, когда возникают исключения. Давайте изменим функцию foo из первого примера:

function foo() {
    return new Promise((res, rej) => {
        throw 'myException';
    });
};

function test() {
    foo();
    console.log(3);
};

и вызовем test(). О, вау, теперь 3 стоит первым (кто-то может подумать, что его вообще не следует выполнять !!!), а неперехваченное исключение myException - вторым. Почему? Потому что движок JavaScript откладывает обработку исключений. Не спрашивайте меня почему, я понятия не имею, но я уверен, что есть причина для этого ... как и для всего. ;)

Вывод: Обещания не делают вещи автоматически асинхронными и всегда await или не используют .then() с функцией, которая возвращает обещание (если вы не ниндзя).

0 голосов
/ 10 октября 2019

Здесь есть две интерпретации «асинхронного», и ответ на оба вопроса «нет», обещания не делают fs.readFileSync любой вид асинхронного.

ПервоеИнтерпретация будет, new Promise ведет себя как setTimeout. Это не так.

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

* между этими реализациями нет никакой разницы *1017*1018 * function getFileContent(filepath){ return new Promise((resolve, reject) => { fs.readFileSync("asd.txt")); }); } и

function getFileContent(filepath){
  fs.readFileSync("asd.txt"));
}

Оба эти вызова fs.readFileSync немедленно на текущем стеке вызовов.

Чтобы сделать функцию "асинхронной" (например, отложитьего выполнение) необходимо использовать setTimeout. Вы можете обернуть это в обещание, но при этом вы не добавляете никаких функциональных изменений, только синтаксический сахар.

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

Единственное исправление - использовать fs.readFile, а не fs.readFileSync. Вот почему существуют несинхронные версии этих функций: невозможно заставить fs.readFileSync , а не разбить вашу программу на большие / медленные чтения.

0 голосов
/ 10 октября 2019

Хорошо, я понимаю, что это был просто пример

Смысл конструкторов Promise в том, что они немедленно выполняют свои executor.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Функция, переданная с аргументами, разрешает и отклоняет. Функция executor немедленно выполняется реализацией Promise, передавая функции разрешения и отклонения (исполнитель вызывается до того, как конструктор Promise даже возвращает созданный объект).

Это означает, что в вашем примере fs.readFileSync выполняется немедленно и (редактируется) блокирует выполнение остальной части вашего кода (см. Комментарий)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...