Почему асинхронный по синхронным функциям? - PullRequest
0 голосов
/ 11 сентября 2018

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

Не могли бы вы подтвердить, пожалуйста, каждое из моих пониманий ниже?

  1. Асинхронные функции хорошо использовать, когда независимая операция (из основного потока программы) длябыть казненным.Не идеально использовать асинхронные функции, когда основная программа требует данных / ответа от асинхронной функции или когда различные независимые асинхронные функции взаимосвязаны.
  2. Нехорошо зависеть от результатавывода асинхронной функции в основной поток программы.Потому что Async всегда выполняется после основного потока.Поэтому, если вам нужно, чтобы некоторые функции выполнялись в основном потоке, лучше определить его как Синхронный, а не асинхронный.
  3. Когда вызываются независимые асинхронные функции, обычно вызывается последующая операция (асинхронная функция), используя обещания или обратные вызовы.
  4. Я все еще могу вызывать функцию синхронизации внутри функции Async.Но если я вызову асинхронную функцию из функции синхронизации, программа может работать не так, как ожидалось, поскольку асинхронная функция будет выполняться только в последний раз?

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Хорошо, давайте посмотрим на это по частям.Просто помните, что Node.js - это однопоточный процесс, и если ему нужно выполнить blocking processes, например, чтение файла (создать указатель события, прочитать дескриптор файла, задать путь к файлу,установить открытый режим и т. д.) лучше использовать асинхронные функции, которые выполняются в отдельном потоке одной и той же страницы или в потоке / пуле.


1) Асинхронные функции хорошо использовать, когданезависимая операция (из основного потока программы) для выполнения.Не идеально использовать асинхронные функции, когда основная программа требует данных / ответа от асинхронной функции или когда различные независимые асинхронные функции взаимосвязаны.

Для начала мы не будемименуйте файл программы как main program, так как в мире Node.js нет подпрограмм (я не говорю о модулях и тому подобное).

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

...
const data = readFile( 'fileName', ( data, output ) => {
    ...
} );
console.log( data ); // this might be null or undefined

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

const data = await readFile( 'filename' );

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


2) Нехорошо зависеть от результата вывода асинхронной функции в основной поток программы.Потому что Async всегда выполняется после основного потока.Поэтому, если вам нужно, чтобы некоторые функции выполнялись в основном потоке, лучше определить его как Синхронный, а не асинхронный.

Здесь вы говорите, что async работает после основного потока.Теперь , что неверно.Позвольте мне нарисовать простую картину оценки и выполнения потока:

Скажем, есть две sync функции A() и B(), и их соответствующие потоки th__A и th__B, они будутпойти примерно так:

th__a ---> th__b

Если они стреляют в порядке A(), то B()Он ожидает оценки первого процесса синхронизации (или блокировки), а затем выполняет второй.Как видно, это НЕ после того, как закончится все выполнение.

Однако, если они теперь являются асинхронными функциями, они будут выполняться параллельно.Скажем, A() был функцией синхронизации, а B() был асинхронной функцией с теми же именами потоков, что и выше, выполнение выглядит примерно так:

th__a     ----
- - th__b   ->

Где - представляет тактовый цикл, а -> представляет конец выполнения.Мы видим, что A() запускается, а затем в новом потоке B() запускается.

Я думаю, это имеет смысл.Теперь, возвращаясь, снова, если вам нужно использовать их немедленно, а затем в качестве асинхронных вызовов, используйте await.


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

Абсолютно.

Скажем, мы определяем функцию sayHello():

const sayHello = () => {
    const P = Q.defer();

    // P.resolve(data);

    // or if there is an exception 
    // P.reject(error);

    return p.promise;
 };

, где Q - отличная библиотека обещаний.Мы можем назвать это как:

sayHello.then( ( data ) => {
    console.log( data ); // P.resolve(..) is working here since the promise was successful.
} ).catch( ( err ) => {
    console.log( err ); // P.reject(..) is working here since there was a problem.
} );

Или вы можете использовать обратные вызовы, такие как fs.readFile(...):

fs.readFile( 'fileName', ( e, data ) => {
    if( e ) { return console.log( e ); } // error was handled
    // perform subsequent functions here with data
} );

4) Iвсе еще может вызывать функцию синхронизации внутри функции Async, но программа может работать не так, как ожидалось, если функция / функция Async вызывается из функции / операции синхронизации, поскольку функция асинхронности будет выполняться только в последний раз?

Не совсем.Обратитесь к пункту (2).Это о нитях.Нестатические процессы.Вы можете очень хорошо вызвать функцию синхронизации внутри асинхронной функции, и она будет отлично работать.

Когда вы читаете файл, скажем, что вы хотите разделить данные на \n или новую строку:

...
if( e ) { return console.log( e ); }
const dataLines = e.split( '\n' ); // this will work brilliantly 
...

Надеюсь, это прояснило все!:)

0 голосов
/ 11 сентября 2018

Фактическое использование асинхронных функций в приложении javascript / node вступает в игру при работе с сетевыми запросами и / или операциями ввода-вывода (или вещами, которые могут занимать много времени).


Пример сетевого вызова

Например, приложение для чата.Клиент (вы) отправляет сообщение какому-либо лицу A. Сообщение отправляется на сервер или непосредственно получателю (p2p) для дальнейшей обработки в соответствии с моделью связи.Вы также хотите отправить другое сообщение другому человеку;человек Б. Но если запросы не обрабатываются асинхронно, клиенту (вам) придется ждать неопределенный период времени;в зависимости от скорости вашей сети, скорости сети получателя, периода ожидания сети или любых других факторов, ответственных за это.

Учтите, что вам нужно подождать 2 единицы времени, чтобы завершить запрос

time:        1                2             3         4                   5        
action: SendToA(message)     waitA         waitA     ResponseFromA       SendToB(message)

Но если тот же запрос является асинхронным.Вы отправляете запрос, который обрабатывается асинхронно клиентом (для связи p2p) или клиентом и сервером для обоих (для клиента / сервера) сообщений.Это то, что на самом деле происходит в браузерах.Браузеры обрабатывают запросы асинхронно, поэтому любая другая часть кода вашего браузера не застревает, пока вы ожидаете завершения запроса.

time:        1                    2                         3                    4                   5          
action: SendToA(message)  waitA/SendToB(message)         waitA/waitB        ResponseFromA       ResponseFromB

Так что в случае синхронизации вы получаете только один запрос напреуспеть в течение 5 единиц времени, в то время как в асинхронном случае вы получите два запроса, чтобы преуспеть в течение 5 единиц времени.

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


Пример чтения / записи ввода / вывода

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

Для синхронизации:

time:        1                       2             3           4                       5        
action: ReadFromFileA(message)     waitA         waitA     ResponseFromA       ReadFromFileB(message)

Для асинхронности:

time:        1                   2                3           4                       5        
action: ReadFromFileA()     ReadFromFileB()   waitA/waitB     ResponseFromA       ResponseFromB

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

Печать - очень своеобразное действие, которое должно быть синхронным.Вы не можете печатать две бумаги асинхронно.

Зависимые функции также должны быть синхронизированы.


Все это говорит о том, что асинхронность является очень мощной функцией при правильном использовании.В приложении реального времени (почти) всегда есть возможности для асинхронности.Если ваше приложение не использует его, ваш пользователь может жаловаться на плохой UX в вашем приложении.

0 голосов
/ 11 сентября 2018

Похоже, вы еще не изучали цикл событий javascript. Здесь - хорошая статья, которой вы можете следовать. Обычно в javascript используется асинхронная функция, чтобы избежать задержки ввода-вывода в процессе, таком как HTTP-вызов в браузере, чтение файла в NodeJS, а не задержка выполнения или параллельное выполнение, поскольку процесс javascript является однопоточным. Если вы хотите больше узнать о неблокирующем вводе-выводе, Здесь - статья, которую я написал о том, как она работает, которая, кажется, отвечает на все ваши вопросы.

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

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