Понимание async и await, внутренних принципов
async — это синтаксический сахар для функции Generator, улучшающий функцию Generator.
- Реализация async заключается в том, чтобы обернуть функцию Generator и автоматический исполнитель в функцию.
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
Функция spawn является автоматическим исполнителем, реализация функции spawn приведена ниже.
function spawn(genF){
return new Promise((resolve, reject)=>{
const gen = genF() // 先将Generator函数执行下,拿到遍历器对象
function step(nextF) {
let next
try {
next = nextF()
} catch(e){
return reject(e)
}
if(next.done){
return resolve(next.value)
}
Promise.resolve(next.value).then((v)=>{
step(()=>{return gen.next(v)})
}, (e)=>{
step(()=>{return gen.throw(e)})
})
}
step(()=> {return gen.next(undefinex)})
})
}
- лучшая семантика
Async и await имеют более четкую семантику, чем asterisk и yield.Async означает, что в функции есть асинхронная операция, а await означает, что следующее выражение должно дождаться результата.
- более широкая применимость
Согласно соглашению модуля co, за командой yield может следовать только функция Thunk или объект Promise, в то время как за ожиданием в асинхронной функции может следовать Promise и значение примитивного типа (числовое, строковое и логическое значение, но в это время он будет автоматически преобразован в немедленно разрешенный Promise.Object, см. Promise.resolve(next.value) в функции порождения
- Возвращаемое значение является обещанием
Удобнее, чем возвращаемое значение функции Generator, быть объектом Iterator, а метод then можно использовать для указания следующей операции.
Вы можете спросить, асинхронность — это синтаксический сахар для функции-генератора, так что же такое функция-генератор?
Синтаксис функции генератора: фокус находится на * и ключевом слове yield
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
Если функция-генератор helloWorldGenerator выполняется, то она не выполняется, а возвращает объект-итератор, после чего необходимо вызвать следующий метод объекта-итератора для перевода указателя в следующее состояние.
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
yield Из-за объекта обхода, возвращаемого функцией Generator, следующее внутреннее состояние можно пройти только путем вызова метода next, поэтому он фактически предоставляет функцию, которая может приостановить выполнение. Выражение yield — это флаг паузы.
Генератор и сопрограмма
Сопрограмма — это способ запуска программы, который может быть реализован с помощью одного или нескольких потоков.
- Концепция сопрограммы:
Когда поток (или функция) выполнен наполовину, он может приостановить выполнение, передать право на выполнение другому потоку (или функции) и возобновить выполнение, когда право на выполнение будет восстановлено позже. Этот поток (или функция), который может выполняться параллельно и обмениваться правами на выполнение, называется сопрограммой.
- Различия между сопрограммами и обычными потоками:
- Обычные потоки являются вытесняющими и будут конкурировать за ресурсы ЦП, в то время как сопрограммы взаимодействуют.
- Далее Одновременно может быть запущено несколько обычных потоков, но работает только одна сопрограмма, а остальные сопрограммы находятся в приостановленном состоянии.
Функция Generator — это реализация сопрограмм ES6, но она не является полной.Функция Generator называется «полу-сопрограммой», что означает, что только вызывающая функция Generator может вернуть выполнение программы функции Generator. В случае полностью выполненной сопрограммы любая функция может продолжить выполнение приостановленной сопрограммы.
Генератор и контекст
Генераторная функция, выполняющая сгенерированный контекст, при встрече с командой yield временно выйдет из стека, но не исчезнет, а все переменные и объекты в нем будут заморожены в текущем состоянии. Когда на нем будет выполнена следующая команда, контекст будет воссоединен со стеком вызовов, а замороженные переменные и объекты возобновят выполнение.
Реализация генератора
Пожалуйста, обратитесь кстатья от allteam
Генератор js обеспечивается не дополнительной поддержкой нижнего уровня движком, а за счет написания кода, для достижения паузы функции и последовательного выполнения. В процессе реализации Generator есть два ключевых момента: один — сохранить контекстную информацию функции, а другой — реализовать идеальный итеративный метод, чтобы несколько выражений yield выполнялись по порядку, чтобы реализовать характеристики. генератора.В основном используется модель конечного автомата, состоящая из случаев переключения, и, кроме того, используется техника замыкания для сохранения контекстной информации функции-генератора.
Regenerator оборачивает функцию генератора вспомогательной функцией и добавляет к ней такие методы, как next/return. В то же время он также упаковывает возвращенный объект генератора, так что вызовы таких методов, как next, наконец, входят в модель конечного автомата, состоящую из случаев переключения. Кроме того, используйте трюк с замыканием, чтобы сохранить информацию о контексте функции генератора.
Вышеупомянутый процесс в основном такой же, как принцип реализации ключевого слова yield в C # Оба принимают идею компиляции и преобразования, используют модель конечного автомата и одновременно сохраняют информацию о контексте функции и, наконец, реализуют новые языковые функции. благодаря новому ключевому слову yield.
Эта ссылка может просмотреть преобразованный код:этот онлайн-адрес