предисловие
Кто-то в групповом чате сказал, что интервью было заданоasync
Принцип реализации и упомянутый в ответеgenerator
, Недавно мне довелось изучить три вещи в заголовке, и я почувствовал, что ответ был немного неуместным.
В этой статье нет подробного анализа исходного кода.Это относится к способу понимания в процессе личного обучения.Если вы хотите узнать, вы можете перейти по ссылке, указанной в статье., если у вас есть какие-либо комментарии/предложения, пожалуйста, укажите.
async
Ниже приводится ответ группы. проблема в томasync
Принцип реализации функции в единой теорииasync
, я чувствую, что сgenerator
Это не имеет значения.
Давайте взглянемMDNОписание на:
async function
используется для определения возвратаAsyncFunction
Асинхронная функция объекта. Асинхронная функция — это функция, которая выполняется асинхронно через цикл событий, который выполняется через неявныйPromise
возвращает свой результат.
смотря наMDNРезультат преобразования на :
For example, the following:
async function foo() { return 1 }
is equivalent to:
function foo() { return Promise.resolve(1) }
Так одинокasync
реализации, он должен больше походить на следующий код:
function _async(fn) {
return (...args) => Promise.resolve(fn(...args));
}
generator
посмотри сноваgenerator
что. Осознайте первымgenerator
для следующегоawait
используется в. Ниже приведеныЛяо Сюэфэн УчебникПример кода в:
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}
var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}
можно понимать как вызовgenerator
на возвращаемый "объект"next
метод, который производит что-то вроде{ value, done }
форма результатов.
Давайте посмотрим на копателейПишите код, как растягивается Цай Сюйиз9k Слова | Обещание / Async / Генератор Принцип реализации Анализ реализациинаписано в этой статьеgenerator
Результат преобразования:
// 代码
function* foo() {
yield 'result1'
yield 'result2'
yield 'result3'
}
const gen = foo()
console.log(gen.next().value)
console.log(gen.next().value)
console.log(gen.next().value)
// babel官网转换结果
"use strict";
var _marked =
/*#__PURE__*/
regeneratorRuntime.mark(foo);
function foo() {
return regeneratorRuntime.wrap(function foo$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return 'result1';
case 2:
_context.next = 4;
return 'result2';
case 4:
_context.next = 6;
return 'result3';
case 6:
case "end":
return _context.stop();
}
}
}, _marked);
}
var gen = foo();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
В процессе обсуждения в группе, для того, чтобы выделитьasync
а такжеawait
, написал следующий "генератор":
function get() {
let g = {
done: false,
count: 0,
next() {
if (this.count === 3) this.done = true;
if (this.done) return { value: this.count, done: this.done };
this.count++;
return { value: this.count, done: this.done };
}
}
return g;
}
let obj = get();
console.log(obj.next())
console.log(obj.next())
console.log(obj.next())
console.log(obj.next())
console.log(obj.next())
// 输出结果
// { value: 1, done: false }
// { value: 2, done: false }
// { value: 3, done: false }
// { value: 3, done: true }
// { value: 3, done: true }
Приведенный выше код иbabel
и реализация в ES определенно сильно отличается, но в основномgenerator
логика выполнения. Для получения подробной информации см.babel
в перекодированном результатеswitch (_context.prev = _context.next)
и несколько строк_context.next = 2;
код.
await
Давайте рассмотримawait
Он может преобразовать логику асинхронного кода в синхронный код, и программа будет приостановлена до поступления возвращаемого значения асинхронного кода. Итак, мы собираемся выбрать фрагмент кода, который заставит программу зависнуть, а именноwhile(true)
. Реализация выглядит следующим образом:
function _await() {
let result = data.next();
while (true) {
console.log('waiting...', result);
if (result.done) return result.value;
result = data.next();
}
}
let g = get();
console.log('before');
let a = _await(g);
console.log(a);
console.log('after');
// 输出
// before
// awaiting... { value: 1, done: false }
// awaiting... { value: 2, done: false }
// awaiting... { value: 3, done: false }
// awaiting... { value: 3, done: true }
// 3
// after
Сделайте еще один шаг вперед
В реальном использовании,await
только вasync
При использовании группы группа друзей спросила, как этого добиться, поэтому была отброшена следующая версия.
function myAwait() {
this.c = function(data) {
if (!this.isCalledByAsync) throw new Error('Should be called by async');
let result = data.next();
while (true) {
console.log('awaiting...', result);
if (result.done) return result.value;
result = data.next();
}
}
}
function myAsync(fn) {
myAwait.prototype.isCalledByAsync = true;
let m = get();
console.log('async before');
let d = new myAwait().c(m);
console.log(d);
console.log('async after');
myAwait.prototype.isCalledByAsync = false;
}
myAsync();
let g = get();
console.log('no async before');
let a = new myAwait().c(g);
console.log(a);
console.log('no async after');
// 输出
// async before
// awaiting... { value: 1, done: false }
// awaiting... { value: 2, done: false }
// awaiting... { value: 3, done: false }
// awaiting... { value: 3, done: true }
// 3
// async after
// no async before
// Error: Should be called by async
Я не придумал никакого другого способа сделать эту отметку, только способ управления прототипом можно использовать для контроля возможности его выполнения, но его можно использовать только вasync
Только для внутреннего пользования.
Эпилог
Эта статья является моим пониманием в процессе личного обучения.Если есть какие-то недоразумения, я приветствую ваши советы.Эта статья также написана для того, чтобы добавить несколько ракурсов к процессу изучения кода.