Предисловие
Впервые я вступил в контакт с обещанием, когда Microsoft выпустила операционную систему Windows 8 в 2012 году и изучала с использованием HTML5 для написания приложений Metro с любопытным отношением. В то время асинхронные интерфейсы в библиотеке Winjs, предоставленные с HTML5, были в форме обещания, которая была для меня просто книгой Небеса, которая только что закончила JavaScript в то время. В то время я думал, что Microsoft снова возилась с этим.
Неожиданно, к 2015 году обещание было фактически записано в стандарт ES6. Более того, опрос показывает, что программисты JS используют эту вещь довольно высоко.
По иронии судьбы, как Microsoft, которая широко использовалась в интерфейсе разработки приложений Metro еще в 2012 году, его собственный браузер IE все еще не поддерживал обещания, пока он не умер в 2015 году. Похоже, что Microsoft не имеет этой технологии, но действительно отказалась от лечения IE. Полем Полем
Оглядываясь назад сейчас, самая проблемная вещь в том, чтобы увидеть обещание в то время, это то, что новички кажутся невероятными, а также наиболее широко восхваленная программами JS -программистами: затем функционирует цепочка вызовов.
Затем, по сути, цепочка вызовов функции состоит в том, чтобы вызвать множественные асинхронные процессы в последовательности. Эта статья начинается с этого момента и изучает и изучает особенность обещания.
Обещание решено
Рассмотрим следующий сценарий, после того, как функция задерживается на 2 секунды, распечатайте линию журналов, затем задерживается на 3 секунды, а затем задерживается на 4 секунды, распечатайте линию журналов. Это очень простая вещь в других языках программирования, но войти в JS труднее, и код, вероятно, будет написан следующим образом:
var myfunc = function () {settimeout (function () {console.log ("log1"); settimeout (function () {console.log ("log2"); settimeout (function () {console.log ("log3");}, 4000);}, 3000);}, 2000);Из-за вложенной многослойной структуры обратного вызова, здесь образуется типичная структура пирамиды. Если бизнес -логика будет сложнее, это станет ужасающим обратным обратном.
Если у вас есть лучшее осознание и знаете, как извлекать простые функции, то код будет выглядеть так:
var func1 = function () {settimeout (func2, 2000);}; var func2 = function () {console.log ("log1"); setTimeout (func3, 3000);}; var func3 = function () {console.log ("log2"); setTimeout (func4, 4000);}; var func4 = function () {console.log ("log3");};Это выглядит немного лучше, но это всегда кажется немного странным. Полем Полем Ну, на самом деле, мой уровень JS ограничен, поэтому я не могу сказать, почему я не могу написать это хорошо. Если вы знаете, почему это не очень хорошо, и поэтому вы изобрели обещание, пожалуйста, дайте мне знать.
Теперь давайте вернемся к делу и поговорим о обещании.
Описание обещания
Пожалуйста, позвольте мне процитировать описание обещания MDN здесь:
Объект обещания используется для отложенных расчетов и асинхронных расчетов. Объект обещания представляет собой операцию, которая не была завершена, но, как ожидается, будет завершена в будущем.
Объект обещания является прокси для возвращаемого значения, которое может быть неизвестно, когда создается объект обещания. Это позволяет вам указать метод обработки для успеха или сбоя асинхронной работы. Это позволяет асинхронному методу возвращать значение, подобное синхронному методу: асинхронный метод возвращает объект перспективы, содержащий исходное возвращаемое значение вместо исходного возвращаемого значения.
У объекта обещания есть следующие состояния:
• В ожидании: начальное состояние, неполнофизированное или отклоненное.
• Выполнено: успешная операция.
• Отклонено: неудачная операция.
Объект обещания с ожидающим состоянием может быть преобразован в полноценное состояние с успешной стоимостью или отклоненным состоянием с отказом. Когда государство переходит, метод, связанный с обещанием. Тогда (ручка функции) будет вызван. (При привязке метода, если объект перспективы уже находится в исполненном или отклоненном состоянии, соответствующий метод будет вызван немедленно, поэтому между завершением асинхронной операции и методом связывания нет условий расы.)
Для получения дополнительных описаний и примеров обещания, пожалуйста, обратитесь к проведению обещания MDN или в запись MSDN.
Попробуйте решить нашу проблему с обещанием
Основываясь на вышеупомянутом понимании обещания, мы знаем, что мы можем использовать его для решения проблемы, что код, стоящий за вложенными многослойными обратными вызовами, глуп и трудно поддерживать. Две ссылки, приведенные выше, уже очень ясны о синтаксисе и параметрах обещания. Я не буду повторять их здесь, просто загрузите код.
Давайте сначала попробуем относительно простой случай, который выполняет только задержки и обратные вызовы:
новое обещание (function (res, rej) {console.log (date.now () + "start settimeout"); settimeout (res, 2000);}). then (function () {console.log (date.now () + "timeout call обратно");});Кажется, что нет никакой разницы в примерах в MSDN, и результат выполнения следующим образом:
$ node fromistest.js1450194136374 START SETTIMEOUT1450194138391
Поэтому, если мы хотим сделать еще одну задержку, то я могу написать это:
Новое обещание (function (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}). Тогда (function () {console.log (date.now () + "Timeout 1 Call Back"); New Spear (function (res, rej) {console.log.log (date -now (rest -set -set -set -set -set -set -iltime); 3000);Кажется, это также работает правильно:
$ node fromistest.js1450194338710 Start Settimeout 11450194340720 Timeout 1 Call Back1450194340720 START SETTIMEOUT 21450194343722
Но код выглядит глупо и мило, верно? Это снова смутно строить пирамиду. Это идет вразрез с целью введения обещания.
Так в чем же проблема? Какова правильная осанка?
Ответ скрыт в возвращаемом значении функции тогда и тогдашней функции обратного вызовов тогдашней функции.
Во -первых, функция Then вернет новую переменную обещания, и вы можете снова вызвать функцию этой новой переменной перспективы, например, это:
Новое обещание (...). Затем (...) .then (...). Затем (...). Затем (...). Затем (...).
Какое промо возвращается тогдашней функцией, зависит от возврата значения обратного вызова.
Фактически, наполненные могут вернуть нормальную переменную или другую переменную обещания.
Если Onfulfiled возвращает нормальное значение, то функция вернет переменную обещания по умолчанию. Выполнение тогдашней функции этого обещания немедленно сделает обещание удовлетворить, и выполняется функция, основанная на подготовке, а параметр overfulfiled ввода является возвращаемым значением предыдущего наполненного.
Если Onfulfiled возвращает переменную обещания, эта переменная обещания будет использоваться в качестве возвращаемого значения функции.
Документы на MDN и MSDN не имеют четкого положительного описания этой серии настроек для тогдашней функции и функции, связанной с наполнением. Что касается официального документа ES6 Ecmascript 2015 (6-е издание, ECMA-262). Полем Полем Я действительно не могу понять свой уровень. Если какой -либо эксперт может объяснить описание двух возвратных значений в официальном документе, оставьте сообщение для совета! ! !
Таким образом, вышесказанное - моя свободная игра, и языковая организация немного сложно описать. Вы поймете после прочтения кода.
Во -первых, случай возврата нормальных переменных:
Новое обещание (function (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}). Тогда (function () {console.log (date.now () + "Timeout 1 Call Back"); return 1024;}). Затем (function (arg) {консоль. arg);Приведенный выше результат выполнения кода:
$ node promistest.js1450277122125 START SETTIMEOUT 11450277124129 Timeout 1 Call Back1450277124129 Последний наполненный возврат 1024
Это немного интересно, верно, но это не ключ. Ключ состоит в том, что функция Onfulfiled возвращает переменную перспективы, что делает нам удобным для подряд несколько асинхронных процессов. Например, мы можем попытаться сделать две операции задержки последовательно:
Новое обещание (function (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}). Тогда (function () {console.log (date.now () + "Timeout 1 Coll Back"); вернуть новое обещание (res, rej) {консоль. 3000);Результаты выполнения следующие:
$ node promistest.js1450277510275 Start Settimeout 11450277512276 Timeout 1 Call Back1450277512276 START SETTIMEOUT 21450277515327 Timeout 2 Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back Back 2
Если вы думаете, что это ничего хорошего, то это не проблема, чтобы сделать это еще несколько раз:
Новое обещание (function (res, rej) {console.log (date.now () + "start settimeout 1"); settimeout (res, 2000);}). Тогда (function () {console.log (date.now () + "Timeout 1 Coll Back"); вернуть новое обещание (res, rej) {консоль. 3000); «Тайм -аут 3 Call Back»);$ node promisTest.js1450277902714 start setTimeout 11450277904722 timeout 1 call back1450277904724 start setTimeout 21450277907725 timeout 2 call back1450277907725 start setTimeout 31450277911730 timeout 3 call back1450277911730 start SetTimeout 41450277916744 Timeout 4 Call Back обратно
Можно видеть, что многочисленные функции с задержкой обратного вызова расположены упорядоченным образом, и нет популярной пирамид, подобной пирамиде. Хотя код вызывает асинхронные процессы, похоже, что все они состоят из синхронных процессов. Это выгодно, обещание приносит нас.
Если у вас есть хорошая привычка перегонять код словеса в отдельные функции, он будет еще красивее:
Функция timeout1 () {return new обещание (function (res, rej) {console.log (date.now () + "timeout1"); settimeout (res, 2000);});} функция timeout2 () {return new обещание (function (res, rej) {console.log (date.now () + "timeout2"); settimeout); TimeOut3 () {return New Promise (function (res, rej) {console.log (date.now () + "timeout2"); settimeout (res, 3000);});} функция timeout3 () {return new обещание (function (res, rej) {console.log (date.now () + "timeout3"); settimeout); timeout4 () {вернуть новое обещание (function (res, rej) {console.log (date.now () + "timeout4"); settimeout (res, 5000);});} timeout1 () .Then (timeout2) .Then (timeout3) .Then (timeout4) .Then (function () () timeout () date. });$ node promistest.js1450278983342 Timeout Timeout11450278985343 Timeout 2145027898351 Timeout31450278992356 Timeout 414502789997370 Timeout4 Callbback
Далее мы можем продолжать изучать проблему передачи в входящих параметрах функции с использованием.
Мы уже знаем, что если предыдущая функция, наполненная наполненной, возвращает нормальное значение, то это значение является параметром записи функции, основанной,; Тогда, если предыдущий наполненный возвращает переменную перспективы, откуда взят параметр записи, наполненного?
Ответ заключается в том, что параметром записи этой функции, находящейся на основе пополнений, является значение, передаваемое, когда функция решимости была вызвана в предыдущем обещании.
Я не мог принять прыжок на некоторое время, верно? Давайте сделаем это хорошо.
Прежде всего, что такое функция обещание Использование оператора от Zou Zou выше MDN
Решите объект обещания с значением успеха. Если значение является продолжительным (затем, то есть с помощью метода, возвращаемый объект обещания «следовать» значению
Короче говоря, это обратный вызов, когда асинхронный вызов успешен.
Давайте посмотрим на то, как выглядит обратный вызов в обычном асинхронном интерфейсе. Возьмите fs.readfile (file [, options], callback), например, на Nodejs. Его типичный пример вызова заключается в следующем
fs.readfile ('/etc/passwd', function (err, data) {if (err) throw err; console.log (data);});Поскольку для функции fs.readfile, успешной или неудачной, она вызовет обратный вызов обратного вызова, поэтому этот обратный вызов принимает два параметра, а именно описание исключения на ошибке ERR и данные результата возврата об успехе.
Итак, если мы используем обещание восстановить этот пример чтения файла, как мы должны его написать?
Во -первых, инкапсулировать функцию fs.readfile:
Функция readfile (filename) {return new обещание (function (Resolve, dize) {fs.readfile (filename, function (err, data) {if (err) {decuct (err);} else {Resiple (data);}});});});};};};};};};Второй - звонок:
readfile ('thefile.txt'). Тогда (function (data) {console.log (data);}, function (err) {throw err;});Представьте, где содержание файла обычно помещается в интерфейс синхронного вызова для чтения файлов на других языках? Правильное ли значение возврата функции? Ответ вышел, какова вход женьшень этой решимости? Это возвращаемое значение, когда асинхронный вызов успешно.
С помощью этой концепции нетрудно понять «входной параметр функции, основанной на подготовке, - это значение, передаваемое при вызове функции разрешения в предыдущем обещании». Потому что задача, проведенная на основе, состоит в том, чтобы обработать результат после успеха предыдущего асинхронного вызова.
Увы наконец выпрямились. Полем Полем
Суммировать
Пожалуйста, позвольте мне использовать кусок кода, чтобы суммировать ключевые моменты, объясненные в этой статье:
function callp1 () {console.log (date.now () + "start callp1"); вернуть новое обещание (function (res, rej) {settimeout (res, 2000);});} function callp2 () {console.log (date.now () + "start callp2"); вернуть новое обещание (function (res, rej) {settimeout (function () {res ({arg1: 4, arg2: "arg2 value"});}, 3000);});} функция callp3 (arg) {console.log (date.now ()) + "start callp3 с arg =" + arg); вернуть новое обещание (function (res, rej) {settimeout (function () {res ("callp3");}, arg * 1000);});} callp1 (). then (function () {console.log (date.now () + "callp1 return"); return callp2 ();}). Тогда (funt.) {rete.sole. ret value = " + json.stringify (ret)); return callp3 (ret.arg1);}). Тогда (function (ret) {console.log (date.now () +" Callp3 return с ret value = " + ret);}) $ node promistest.js1450191479575 start callp11450191481597 callp1 return1450191481599 start callp21450191484605 callp2 return с ret value = {"arg1": 4, "arg2": "arg2 value"} 1450114846050501301013013013013050101010101 годы. 41450191488610 Callp3 return с ret value = callp3Приведенный выше простой опыт обучения использования обещания для решения многослойных асинхронных вызовов-это все контент, которым я делюсь с вами. Я надеюсь, что вы можете дать вам ссылку, и я надеюсь, что вы сможете поддержать Wulin.com больше.