[Скромное мнение] Callback Hell and Promise

JavaScript
Асинхронное программирование очень важно в JavaScript, но слишком много асинхронного программирования также приводит к проблеме вложенности обратных вызовов.

Что такое функция обратного вызова?

ajax(url, () => {});

Приведенный выше код является функцией обратного вызова. Функция как параметр должна зависеть от другой функции для выполнения вызова.

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

Что такое ад обратного вызова?

let form = document.querySelector('form');
form.onsubmit = function (e) {
  var name = document.querySelector('input').value;
  $.ajax({
    url: "http://demo.com/submit",
    type:'POST',
    data: {name: name},
    success: function(res) {
        if (res.code === 2000) {
            var h1 = document.querySelector('h1').innerHTML;
            h1.innerHTML = res.data.name;
        }
    }
  });
}

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

Основные проблемы и недостатки callback hell:

  1. Вложенные функции связаны, и как только они будут изменены, они повлияют на все тело.
  2. Когда много вложенных функций, становится сложно обрабатывать ошибки
  3. Функция обратного вызова используется для использования ошибок try...catch...capture, а не RETURN напрямую.

Как решить ад обратного вызова?

Основная причина в том, что из-за привычек кодирования разработчиков мы можем решить ее следующими способами:

  • Сохраняйте стиль кода коротким, старайтесь использовать именованные функции и избегайте анонимных функций.

document.querySelector('form').onsubmit = onFormSubmit();

function onFormSubmit(e) {
  var name = document.querySelector('input').value;
  $.ajax({
    url: "http://demo.com/submit",
    type:'POST',
    data: {name: name},
    success: onSuccess(res)
  });
}

function onSuccess(res){
    if (res.code === 2000) {
        var h1 = document.querySelector('h1').innerHTML;
        h1.innerHTML = res.data.name;
    }
}

  • Модульность, разделение каждой независимой функции, инкапсуляция, упаковка в отдельный файл js, импорт через импорт

// formHandler.js
module.exports.formSubmit = onFormSubmit;

function onFormSubmit(e) {
  var name = document.querySelector('input').value;
  $.ajax({
    url: "http://demo.com/submit",
    type:'POST',
    data: {name: name},
    success: onSuccess(res)
  });
}

function onSuccess(res){
    if (res.code === 2000) {
        var h1 = document.querySelector('h1').innerHTML;
        h1.innerHTML = res.data.name;
    }
}

// index.js
var formHandler = require('./formHandler');
document.querySelector('form').onsubmit = formHandler.formSubmit;
  • Обрабатывайте каждую ошибку, кодируйте в соответствии со стандартными спецификациями
  • Promise/Gengenerator/Async Function
В дополнение к обычным функциям обратного вызова, таким как асинхронная обработка, есть промисы, генераторы и асинхронная обработка асинхронной обработки.

Каковы характеристики промисов?

Обещание переводится как обещание, которое обещает точный ответ в будущем и в будущем, причем обещание имеет три состояния:
  1. в ожидании
  2. завершено (решено)
  3. Отклонено (отклонено)

Государство обязалось изменить будущее, вы не можете изменить государство

Когда мы конструируем Promise, когда внутри кода конструктора выполняется сразу

new Promise((resolve, reject) => {
  console.log('new Promise')
  resolve('success')
})
console.log('finish');

// new Promise
// finish

Promise
Реализованы связанные вызовы, то есть каждый вызов затемПосле этого он возвращает обещание, и это совершенно новый Promise, а также потому, что состояние неизменно. если ты в товозврат используется вЗатем вернитесьЗначение будет разрешено Promise.resolve()Упаковка

Promise.resovle(1)
    .then(res => {
        console.log(res); // 1
        return 2; // 包装成了 Promise.reslove(2)
    })
    .then(res => {
        console.log(res); // 2
    })

Обещания также решают проблему адского обратного вызова:

// old
ajax(url, () => {
    // 处理逻辑
    ajax(url1, () => {
        // 处理逻辑
        ajax(url2, () => {
            // 处理逻辑
        })
    })
})

// new
ajax(url)
    .then(res => {
        console.log(res);
        return ajax(url1);
    })
    .then(res => {
        console.log(res);
        return ajax(url2);
    })
    .then(res => console.log(res));

асинхронно и жду

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

async используется для объявления функции асинхронной, а await используется для ожидания завершения асинхронного метода.


Продолжение следует...