В предыдущем упражнении
мы узнали о двух новых аспектах JavaScript,
их поддержке функций первого класса и закрытия.
Мы также видели, как Node обрабатывает аспект асинхронного программирования и как
Node поддерживает асинхронное выполнение кода с
использованием обратных вызовов, а также обработки ошибок.
Давайте посмотрим на пример того, как мы используем это
в нашем приложении Node в этом упражнении.
Продолжая с того, где мы остановились в предыдущем упражнении,
теперь я собираюсь пойти и изменить модуль прямоугольника Node,
чтобы он мог принять помощь обратных вызовов.
Поэтому я собираюсь удалить эти экспорты здесь,
и вместо этого они собираются изменить эту функцию.
Я собираюсь использовать эти две функции немного позже,
поэтому я сохраняю их внизу.
Так что позволь мне держать их в стороне.
И тогда я изменю этот прямоугольный модуль следующим образом.
Так что скажем module.exports.
Таким образом, мы используем стандартный способ обработки модуля.
И это будет экспортировать эту функцию, которая принимает эти три параметра,
x и y и обратный вызов.
Обратный вызов - это функция, которая будет поставляться при вызове этого модуля.
Таким образом, это использование функций первого класса, о которых мы говорили ранее.
Таким образом, внутри этого обратного вызова,
чтобы вы могли видеть, что вы получаете два параметра
, x и y. В этом случае для прямоугольника,
x и y соответствуют длине и ширине
прямоугольника, который передается в качестве двух значений.
Итак, внутри здесь, мы собираемся проверить,
если х меньше или равно нулю или у меньше или равно нулю.
Мы написали такой код здесь.
Поэтому я просто скопирую этот код отсюда,
а затем принесу его сюда, а затем мы отредактируем.
Таким образом, в этом случае, это если x
меньше или равно нулю или y меньше или равно нулю.
В этом случае, что нам делать?
В этом случае мы замечаем, что
размеры прямоугольника меньше или равны нулю.
Так что мы должны справиться с этим по-другому,
и мы сделаем остальную часть этого.
Другая часть, где мы обрабатываем ситуацию, когда прямоугольник является допустимым прямоугольником.
Таким образом, в этом случае
мы будем делать, это использовать setTimeout.
Итак, здесь я имитирую тот факт, что все, что
делается в этом прямоугольнике, займет некоторое время.
Таким образом, это асинхронная обработка.
Теперь, поскольку у меня нет большой работы в фоновом режиме,
поэтому я собираюсь имитировать это, просто используя
функцию setTimeout JavaScript, а затем
задержку перед вызовом функции обратного вызова.
Таким образом, я организую это следующим образом.
Поэтому внутри setTimeout
я собираюсь вызвать эту функцию
и организовать задержку в
2 000 миллисекунд или две секунды, после чего эта функция будет вызвана.
Поэтому, если вы помните,
setTimeout, который поддерживается в JavaScript,
он принимает в качестве первого параметра функцию, а
вторым параметром будет период времени, для которого это будет отложено.
Так что позвольте мне отстукнуть это.
Теперь мне нужно заполнить эту функцию здесь.
Поэтому я начал с функции стрелки здесь,
которая не принимает параметров, а затем, когда вызывается,
я собираюсь выдать вызов обратному вызову.
Этот обратный вызов является функцией обратного вызова, которая
будет передаваться в качестве третьего параметра здесь.
Эта функция обратного вызова, как вы заметили, принимает два параметра.
Первый - это ошибка, а второй - возвращаемое значение.
Итак, в этом случае, поскольку у нас есть ошибка,
потому что x меньше или равно нулю и y меньше или равно нулю,
поэтому первое значение, которое я собираюсь передать как новая ошибка,
и эта ошибка является именно той строкой, которую я использовал в console.log тогда,
и это то, что я передам как ошибка здесь.
Позвольте мне теперь удалить этот console.log,
он мне больше не нужен.
Поэтому для обратного вызова
я собираюсь сгенерировать новый объект ошибки, а затем передать это
в качестве возвращаемого значения для функции обратного вызова, первого параметра.
Поэтому я скажу, что размеры прямоугольника должны быть больше нуля.
Итак, мы скажем l,
это значение x и y, которое мы получили в качестве входных значений там.
Так что это обратный вызов.
И вторая часть этого обратного вызова,
я собираюсь передать как null, потому что это вернет ошибку.
Поэтому, когда вы возвращаете ошибку в качестве первого параметра,
второй параметр будет игнорироваться, когда этот обратный вызов был только что получен
модулем узла, откуда мы вызываем эту конкретную функцию там.
Итак, с этой договоренностью,
так меньше нуля,
так что позвольте мне дать немного места здесь, чтобы он был правильно отступом здесь.
Итак, способ, который я устраиваю
здесь, заключается в том, что если x меньше нуля и y меньше нуля,
я собираюсь обратный вызов функции обратного вызова, которая была передана,
но первый параметр будет передан по
ошибке, потому что здесь мы замечаем, что есть ошибка,
а второй параметр будет нулевым.
Если это не так,
то я собираюсь вызвать тот же обратный вызов,
но с первым параметром.
Так что позвольте мне скопировать этот код здесь.
Я все еще собираюсь использовать setTimeout здесь.
Но эта первая часть не будет ошибкой
, а первая часть,
в данном случае, ошибки нет.
Поэтому я просто собираюсь передать это значение как null.
Таким образом, это означает, что ошибка имеет значение null.
Таким образом, это допустимый прямоугольник.
Таким образом, мы можем вычислить значения для прямоугольника.
Но вместо этого я просто передаю
объект JavaScript, содержащий две функции в
качестве двух значений внутри этого объекта JavaScript.
Итак, здесь я возьму эти два,
периметр и площадь,
а затем эти два будут переданы в качестве двух значений здесь,
периметр и площадь.
И эти два, так как они являются объектом JavaScript,
поэтому периметр и площадь будут
двумя свойствами, которые я передам внутри этого объекта JavaScript,
и это все.
Итак, во втором случае
ошибка устанавливается в null, потому что ошибки нет,
но вторая часть,
обратите внимание, что я передаю объект JavaScript, содержащий два свойства,
периметр и площадь, которые являются двумя функциями здесь.
Таким образом, две функции являются функцией периметра и функцией площади.
Таким образом, этот объект JavaScript будет передан обратно
в качестве возвращаемого значения для обратного вызова здесь, второе значение.
И снова, я собираюсь отложить это на
два второго интервала, прежде чем значение будет передано обратно этой функцией.
Причина, по которой я использую setTimeout, заключается в имитации
задержки до того, как обратный вызов поступит с другой стороны.
Таким образом, этот вид представляет ситуации, когда, например,
вы выдаете вызов базы данных в базу данных,
и база данных должна быть прочитана, прежде чем значение будет передано вам обратно.
Так что это займет определенное количество времени.
Поэтому я в основном моделирую это в данный момент, используя функцию setTimeout здесь.
Позже вы увидите, что когда мы интегрируем MongoDB с
нашим Express в последующих упражнениях,
что задержка должна быть смоделирована,
она будет автоматически вызвана из-за того, что вам нужно делать
операции с базой данных за кулисами до получения данных.
Итак, здесь, завершив обновление модулей прямоугольника,
поэтому здесь вы видите, что модуль прямоугольника принимает
три параметра, поскольку это входной вызов здесь,
x, y и обратный вызов.
Итак, обратный вызов - это функция обратного вызова, которая поставляется здесь.
И эта функция обратного вызова будет вызываться внутри здесь,
и когда вызывается функция обратного вызова,
либо вы передаете ошибку, либо
передаете обратно функцию, которая позволяет вычислить периметр и площадь прямоугольника.
Теперь этот шаблон вызова и передачи функции обратного вызова
из одного модуля Node, а затем второго модуля Node, который, когда он завершит,
будет передавать результат, используя функцию обратного вызова, является
именно шаблоном, который вы увидите часто повторяющиеся в приложениях Node.
Вот почему я иллюстрирую это.
Конечно, это надуманный пример, который я иллюстрирую здесь, но он показывает
все стандартные шаблоны, которые вы будете использовать с
функциями узла и обратного вызова, а также обработку ошибок.
Теперь мы обновили модуль прямоугольника здесь.
Давайте исправим этот файл index.js, чтобы он мог передавать функцию обратного вызова, а
затем обрабатывать возвращаемое значение, которое отправляется обратно из модуля прямоугольника.
Возвращаясь к index.js,
теперь мы собираемся обновить файл index.js следующим образом.
Вместо этого я удалю это из файла index.js.
Здесь, то, что мы будем делать, это вызвать
этот прямоугольный модуль, а
затем передать в l и b в качестве двух параметров.
И третий параметр, который я собираюсь передать, - это функция обратного вызова.
Таким образом, функция обратного вызова имеет два параметра, err и прямоугольник.
И эта функция обратного вызова реализуется следующим образом.
Итак, здесь вы видите, что я вызываю
этот прямоугольный модуль узла,
и я передаю длину и ширину первых двух параметров.
И третий параметр - это, конечно,
функция обратного вызова, которую я реализую здесь.
Итак, это функция стрелки, которую я реализую здесь.
Итак, внутри этой функции обратного вызова,
как мне обрабатывать возвращаемое значение?
Поэтому здесь я скажу, if (err),
поэтому, если вам возвращается значение ошибки, я
просто сделаю console.log, и я скажу
«ERROR», а затем второе значение - err.message.
Напомним, что в прямоугольнике
мы создали этот новый объект ошибки,
а затем передали эту строку внутри этого объекта ошибки.
Эта строка будет прикреплена к
объекту ошибки к свойству message объекта ошибки здесь.
Итак, в файле index.js,
поэтому я извлекаю свойство сообщения объекта ошибки,
а затем печатаю его на моей консоли здесь.
Поэтому, если произойдет ошибка,
я собираюсь распечатать сообщение об ошибке, используя это.
Итак, вот как я буду обрабатывать ошибку, которая была возвращена функцией обратного вызова.
В противном случае, конечно, в этом случае
модуль прямоугольника вернул функцию прямоугольника,
объект, который содержит периметр и функции области,
поэтому я могу идти вперед и распечатать это значение.
Итак, здесь я скажу площадь
прямоугольника размеров l равна,
так что я скажу,
и b равно.
Причина, по которой я идентифицирую его
явно, станет очень ясной, когда мы запускаем этот пример.
Я скажу, что прямоугольный.area.
Теперь обратите внимание, что для этой области
я не отправляю никаких параметров здесь, потому что идет к значениям,
длина и дыхание были переданы уже здесь, в l и b,
и они будут уже доступны для этого
и здесь из-за закрытия, которое поддерживает JavaScript.
Поскольку эти x и y вошли в качестве параметров,
поэтому они будут доступны прямо там в этой функции обратного вызова.
Таким образом, эти x_y будут автоматически доступны для нас здесь.
Итак, на самом деле,
мне не нужно предоставлять эти параметры x и y здесь вообще, потому что
эти x и y будут извлечены из этих x и y прямо там.
Так что мне даже не нужно передавать эти два значения здесь.
Вот почему, прямо там,
я могу вызвать rectangle.area.
И это вычисление площади автоматически получит l и b, которые были переданы
путем вызова прямоугольника к модулю прямого узла ранее.
Таким образом, это закрытие JavaScript, работающего здесь.
Итак, это первый.
Я печатаю область прямоугольника.
То же самое, позвольте мне распечатать периметры.
Так что, чтобы распечатать периметры,
так что я скажу console.log.
Периметр прямоугольника будет представлять собой периметр прямоугольника.
Теперь я должен сказать вам, что такой подход для реализации требует немного
усилий, чтобы понять и интернализировать способность асинхронной функции.
Требуется некоторое время для того, чтобы полностью понять, как это работает на самом деле.
Теперь, чтобы проиллюстрировать тот факт, что
этот вызов функции приведет к вызову модуля Node,
но эта часть будет выполнена только после
двухсекундной задержки из-за того, что мы используем заданную метку времени.
Теперь, когда мы изучали асинхронную работу,
потому что мы перешли от обработки к спине,
позвольте мне также представить еще один console.log здесь, чтобы сделать точку зрения.
Так что мы скажем, что это
заявление после вызова rect.
Причина, по которой я иллюстрирую этот момент, заключается в том, что когда вы выдаете
этот вызов, этот код не будет выполнен до двухсекундной задержки.
Таким образом, пока
ваша функция, основная функция здесь,
будет продолжаться, а затем выполнять следующую строку кода, который вы видите здесь.
Так что это продолжение, которое вы увидите здесь.
Итак, с этими изменениями,
давайте сохраним изменения, а затем посмотрим, как это приложение выполняется сейчас.
Так что сохраняя изменения.
Давайте перейдем к терминалу и выполним этот узел приложения.
Теперь, перейдя к терминалу, добавьте подсказку.
Позвольте мне ввести npm start, и вы сразу
заметите, что решение и это заявление были распечатаны ранее.
И затем после этой определенной задержки,
площадь и периметр были распечатаны.
Таким образом, это двухсекундная задержка, которую мы ввели с использованием заданного тайм-аута.
Итак, вы заметили, что в более ранней версии
это было напечатано, и сразу же под ним была напечатана область и периметр.
Но теперь обратите внимание, что эти значения печатаются немного позже.
Таким образом, между ними их вызовы функций с различными параметрами, которые уже
вошли, а затем обратные вызовы вызываются после двух секунд задержки для каждого из них.
И из-за того, что есть закрытие, которое поддерживает JavaScript,
поэтому значения, которые передаются, сохраняются.
И поэтому, когда вызывается функция обратного вызова,
печатается соответствующее значение.
Вот почему вы видите, что площадь и
периметр напечатаны правильно и эти два здесь,
эти два утверждения здесь,
соответствуют этому конкретному вызову прямого
с l равно два и b равно четырем.
И тогда эти два,
рядом с двумя, конечно,
соответствуют этому конкретному, а остальные, как вы видите здесь.
Итак, я хотел проиллюстрировать тот факт, что при асинхронном вычислении
асинхронное вычисление занимает свое собственное время,
чтобы вернуть значение, в то время как ваше основное вычисление
будет продолжаться вперед, не дожидаясь завершения обратного вызова.
Итак, когда вам нужно выполнить определенный объем работы,
вы передали в качестве обратного вызова этому другому модулю.
И когда этот другой модуль завершит свою работу,
он будет обратный вызов, а затем этот код будет выполнен.
Вот тот момент, который я проиллюстрировал, используя этот пример.
Опять же, как я уже сказал,
это требует немного воображения и понимания
для вас, чтобы интернализировать, как это работает,
но вы увидите, что с Node, а также Express, и когда мы используем MongoDB,
вы увидите такой шаблон, повторяющийся очень часто в том, как мы пишем наш код.
Таким образом, с помощью этой простой иллюстрации обратных вызовов и обработки ошибок
мы завершаем это упражнение.
Это хорошее время для вас сделать комментарий с этим сообщением,
узлом, обратными вызовами и обработкой ошибок.