Поймите, как асинхронная работа выполняется в JavaScript, на основе обратного вызова, обещаний и асинхронного/ожидания.
Прежде всего, давайте поймем идею асинхронного кода. Принимая человеческое тело в качестве типичной идеи, у нас есть много органов и систем, которые могут соединяться и общаться друг с другом, наши системы тела выполняют определенную задачу или группу задач, теперь представьте, что вы не слышите, пока видите? Я имею в виду, если вы слушаете кого -то, что ваш мозг не сможет действовать с данными, поступающими с глаз? Или вы не можете думать во время прогулки? В основном ожидание одной вещи, прежде чем мы перейдем к следующему. Наша жизнь была бы ужасно медленной! Однако мы не работаем так и не благодарим Бога за это, все наши системы функционируют одновременно, мы можем слышать, видеть, чувствовать, говорить все одновременно без хлопот, когда приходят сигналы от глаза, Brain стреляет в ответ на это, и если сигналы для слуха также доступны, он реагирует на это.
Идея асинхронных операций заключается в том, что наш код не должен застрять потом! Это пригодится, когда мы захотим что -то, что займет некоторое время, поэтому наш код не замораживает и не портит UX для пользователя. Существуют разные средства, которые JavaScript использует для достижения асинхронных операций, хотя сам JavaScript является единственным потоком, это подразумевает, что код, записанный в JavaScript, выполняет только одну задачу за раз, асинхронная операция JavaScript с помощью следующих средств:
- Однако JavaScript также является функциональным языком, и это означает, что мы можем передавать функции в качестве аргументов для функций, и если функция, которую мы выполняют, зависит от значения в основной функции, она будет ждать ее.
- Мы также можем использовать обещания, чтобы справиться с ними, и у них есть более чистый синтаксис, чем код на основе обратного вызова.
- Async/ждать, и это самый простой способ управления асинхронным кодом
//Normal Synchronous code let hero = 'spiderman' console.log(hero) let hero2 = 'Antman' console.log(hero2)
Следующий код выберет Spiderman до того, как Antman докажет, что JavaScript является однопоточным, однако браузер предоставляет полезный API, метод settimeout (), это добавляет функцию в очередь после истечения заданного времени, функция SetTimeout принимает два параметра как Аргументы, функция и целое число, которое является представлением количества времени, которое мы хотим пройти в миллисекундах, прежде чем мы назваем фонд, мы передаем его в качестве аргумента.
console.log('starting')
setTimeout(()=> console.log('timeout ran'), 300)
console.log('before timeout')
И мы видим, что до того, как тайм -аут будет зарегистрирован на консоли, а затем следуют Timeout Ran, если мы оставим аргумент для пустого времени, он все равно будет вести себя так же, что в основном этот API говорит браузеру добавить наш код в стек вызовов через некоторое время , которое, возможно, время, которое нужно получить ресурсы или сделать некоторую работу, и это является основой кода обратного вызова, давайте посмотрим на код на основе обратного вызова.
Callbaclk на основе кода
Код на основе обратного вызова, как правило, является первым решением асинхронного программирования, и он включает в себя передачу функции в качестве аргумента другой функции, функция, которую мы пропустили в качестве аргумента, будет задержать выполнение до тех пор, пока начальная функция не завершится, а затем функция, которую мы передали в качестве обратного вызова, будет Беги, давайте посмотрим на типичный пример;
console.log('starting')
let fun = (cb) => {
let myHero = 'hulk'
let hero = 'Cyborg'
let heroI = 'Superman'
setTimeout(()=> cb([myHero, hero, heroI]))
}
fun((hulk)=> {
myHeroes = hulk
console.log(myHeroes)
}
)
let myHeroes;
console.log('before timeout')
//logs out
// starting
// before timeout
// ['hulk', 'Cyborg', 'Superman']
Очевидно, что мы видим, что «до тайм -аута» выйдет в консоль, прежде чем забавная функция выходит из Myheroes, даже если мы называем забавную функцию, прежде чем выйдем из входа «перед тайм -аутом» в консоли, это JavaScript, сообщающий нашему коду продолжать до следующей задачи и когда у нас есть результат от развлечения, войдите в консоль. Это типичный пример того, чтобы сделать наш код асинхронным, давайте посмотрим на типичный случай использования обратных вызовов с HTTP -запросом с использованием объекта Xmlhttprequest. Это API, который доступен в браузере, и он позволяет нам делать HTTP -запрос, не нарушая UX, он ведет себя асинхронно, что означает, что он может начать, а затем закончить в какой -то момент. Мы напишем простую многоразовую функцию, которая позволяет нам получать данные из некоторых ресурсов и сделать что -то в этом
let request = function(url, cb){
let XHR = new XMLHttpRequest();
XHR.open('GET', url, true)
XHR.send(null)
XHR.onload = function(){
if(this.status === 200){
cb(undefined, XHR.response)
}
else if(XHR.status !== 200){
let err = { message: 'Error fetching resource', status: XHR.status}
cb(err, undefined)
}
}
}
Наша функция запроса будет вызвана с двумя аргументами: URL -адрес ресурса, который мы хотим получить, и функция обратного вызова, функция обратного вызова имеет доступ к двум параметрам, объект ошибки, если есть один и данные, которые представляют ресурс, который мы пытались Получите, если это было найдено, давайте назовем эту функцию и попытаемся получить некоторые данные от JSON Todos Placeholder
console.log('before request')
console.log(1)
request('jsonplaceholder', (err, data) => {
if(!err){
console.log('request completed', data)
}
else{
console.log('request completed', err)
}
)
console.log('request made')
console.log(3)
Мы должны увидеть ресурс, зарегистрированный в консоли, если он был успешно получен, или мы видим объект ошибки, зарегистрированный в консоли. Это круто, потому что он многоразовый, и он отказывается от некоторого кода, однако это может легко превратиться в треугольник гибели, если нам пришлось получить еще немного ресурса, когда мы получили первый ресурс, наш код может легко забиться
request('jsonplaceholder', (err, data) => {
console.log('request completed', data)
request('jsonplaceholder', (err, data) => {
console.log('requset completed', data)
request('jsonplaceholder', (err, data) => {
console.log(data)
})
})
)
Наш код просто приобретает эту глубину в нее, и если есть ошибка, как мы узнаем, где ошибка ??? Допустим, мы создаем отдельную функцию обработчика ошибок и сделаем ее многократным использование, однако у нас все равно будет треугольник смерти, вместо того, чтобы использовать обратные вызовы, которые вы можете использовать обещаниями.
Обещания
Обещания представляют собой более чистый способ выполнения асинхронных задач, обещание в основном вернет результат асинхронного процесса, и вы можете получить доступ к этому методу обработки данных, или метод захвата для обработки ошибок, давайте посмотрим на базовый синтаксис обещать
console.log('before myProm called')
let myProm = new Promise((resolve, reject) => {
if(1 < 2) resolve(true)
})
console.log('myProm defined')
myProm.then(data => console.log('got data back', data))
console.log('after myProm called')
//logs out
//before myProm called
//myProm defined
//after myProm called
//got data back true
Мы видим, что код в тогдашнем методе упускается в последнее время, доказывая, что обещания являются асинхронными. Обещание объявляется с использованием конструктора перспектива, оно выполняет функцию в качестве аргумента, и эта функция мы передаем в качестве аргумента обещания, принимая два параметра, разрешают и отвергают. Мы используем Call Resolve, чтобы вернуть значение из обещания, если все в порядке, мы называем «Отказаться», чтобы вернуть ошибку, если что -то не так. Раскрытые данные могут быть доступны с использованием метода тогдашнего, он принимает аргумент аргумента, представляющий данные, которые разрешены обещанием, и в приведенном выше примере мы просто ввели их в консоль. Мы не обрабатывали сбои в нашем вышеуказанном примере, но если произошел сбой, мы используем параметр отклонения и отклоняем его значение, данные, возвращаемые методом отклонения что для обработки ошибок. Давайте посмотрим на типичный случай, когда обещание не удалось.
console.log('before myProm called')
let myProm = new Promise((resolve, reject) => {
let myVar = 10;
if (1 >= myVar){
resolve(true)
}
else{
reject(false)
}
})
console.log('myProm defined')
myProm.then(data => console.log('got data back', data))
.catch(err => console.log('oops something happened', err))
console.log('after myProm called')
//logs out
//before myProm called
//myProm defined
//after myProm called
//oops something happened false
Обещание в приведенном выше примере отклоняется, потому что ясно, что 1 не больше или равно 10, поэтому мы называем отклонение и передаем его ложным в качестве аргумента, и когда мы обрабатываем эту ошибку, мы видим ложное оператор, мы также можем передать в объектах В качестве значений метода отклонения и разрешения давайте изменим нашу функцию XHR для использования обещаний вместо обратных вызовов
let request = function(url){
return new Promise((resolve, reject) => {
let XHR = new XMLHttpRequest();
XHR.open('GET', url, true)
XHR.send(null)
XHR.onload = function(){
if(this.status === 200){
resolve(this.responseText) //new addition
}
else if(XHR.status !== 200){
let err = new Error('Error fetching resource')
err.status = XHR.status
reject(err) //new addition
}
}
})
}
//requesting our data
request('data.json')
.then(data => console.log(data))
.catch(err => console.log(err))
//logs out the data
Я полагаю, что вы согласитесь со мной, что приведенный выше пример является гораздо более чистым и легким способом написания асинхронных задач, прохладных и аккуратных, и если мы хотим сделать несколько запросов, которые зависят от более ранних запросов, у нас не будет такого треугольника Глубина поедания в наш код, и нам не нужно беспокоиться о том, чтобы отменить ад, давайте посмотрим на типичный вариант использования
request('data.json')
.then(data => {
request('data.json')
.then(data => console.log(data))
})
.catch(err => console.log(err))
Мы видим, что наш код все еще выглядит чище, и мы все еще понимаем, что происходит, нам нужно только один раз вызвать метод улова, и он обрабатывает любые отрицания обещания в коде, даже если мы обещаем звонить после обещания, я думаю, что это с легче работать, чем обратные вызовы. Обещания крутые, хотя у них все еще есть свои недостатки, и с большим количеством запросов, которые можно сделать, наш код может легко начать выглядеть грязным, слава Богу за то, что у нас есть асинхронность/ждать.
Асинхрон/жду
Async/await – это новая особенность JavaScript, которая облегчает обработку асинхронной, мы можем пометить функцию быть асинхронной, используя асинхро ключевое слово А потом мы используем Ждите Ключевое слово, чтобы дождаться какой -то асинхронной задачи и продолжать писать другую логику в нашей функции. Async/await – это значительно улучшенный способ решения обещаний, давайте посмотрим, как мы можем использовать асинхронное/ждать с асинхронной задачей, мы все еще используем функцию запроса, которую мы объявили, используя обещание;
let getResource = async () =>{
let response = await request('data.json')
console.log(response)
}
getResource()
Вы посмотрите на это и удивляетесь, почему я не встал прямо в асинхронность/ожидаю? Async/wait делает асинхронные задачи мечтой, как показано выше, когда мы используем ключевое слово Async для обозначения функции как асинхронное значение в какой -то момент мы сделаем какую -то форму асинхронной работы, а затем внутри функции мы используем ключевое слово wwait перед асинхронной операцией И в нашем случае это функция запроса, теперь это то, что произойдет; Функция начнет выполнять, и когда она столкнется с ключевым словом Await, она приостановит функцию и перейдет к следующему, когда значение из запроса будет доступно, оно продолжается с асинхронной функцией, и мы видим, как наши данные вышли из консоли. Ключевое слово waw просто ожидает обещания оценить и вернуть значение или ошибку, а затем мы продолжим с остальной частью кода. Вот и для этой статьи, надеюсь, вы найдете ее полезным, хорошего дня.
Оригинал: “https://dev.to/kalashin1/mastering-asynchronous-operations-in-javascript-1712”