Три асинхронных решения в ES6

внешний интерфейс Promise
Некоторые случаи взяты из руководства Ruan Yifeng по ES6.

Предварительная подготовка знаний

  1. Выполнение функции генератора вернет итератор (Iterator), метод next() может быть вызван на итераторе для выполнения следующего yield или return
  2. Вызов метода next() вернет объект{value: res, done: false}, значение value — это значение выражения после yield, значение done указывает итератору, был ли он выполнен (последний yield или return )
  3. Метод next() может передавать значение как возвращаемое значение предыдущего выражения yield.

Обладая этими знаниями, вы можете сделать объект Promise значением доходности с исполнителем для обработки асинхронных операций.

Метод 1: генератор + обещание + исполнитель

const fs = require('fs')

// Promise 版的readFile
const readFile = function (fileName) {
  return new Promise(function(resolve, reject) {
    fs.readFile(fileName, function(err, data){
      if (err) return reject(error);
      resolve(data);
    })
  })
}

const gen = function * () {
  let f1 = yield readFile('a.txt');
  let f2 = yield readFile('b.txt');

  console.log('F1--->', f1.toString());
  console.log('F2--->', f2.toString());
}


// 基于 Generator 和 Promise 的自动执行器
function run(gen) {
  let g = gen();
  function next(data) {
      let result = g.next(data);    
      (!result.done&&result.value) && result.value.then(next); 
  }  
  next();
}


run(gen);

Результат.значение в исполнителе теперь является обещанием, получить требуемый результат с помощью метода then, передать следующий метод в следующий раз, поэтому let f1 = yield readFile('a.txt'); вы можете получить значение!

Способ 2: Генератор + функция Thunk + исполнитель

const fs = require('fs')

// 把一个单一执行的函数 ,变成需要再次调用的函数,固定一部分参数
function thunkify(fn, obj = {}) {
    return function () {
        let args = Array.from(arguments);
        return function (m) {
            args.push(m)
            return fn.apply(obj, args)
        }
    }
}

const readFile = thunkify(fs.readFile, fs);

const gen = function* () {
    let f1 = yield readFile('a.txt');
    let f2 = yield readFile('b.txt');

    console.log('F1-->', f1.toString());
    console.log('F2-->', f2.toString());
}


// 基于 Generator 和 Thunk函数的自动执行器
function run(fn) {
    let gen = fn();

    function next(err, data) {
        let result = gen.next(data);
        if (result.done) return 1;
        result.value(next);
    }

    next();

}

run(gen);

Преобразователь Thunk здесь преобразует исходную функцию fs.readFile в функцию, которую нужно вызывать дважды.Результат выполнения readFile можно передать через функцию обратного вызова в качестве параметров, а затем передать следующему методу.

Способ 3: метод асинхронной обработки, основанный на асинхронной функции и ожидании

const fs = require('fs')

// Promise 版的readFile
const readFile = function (fileName) {
  return new Promise(function(resolve, reject) {
    fs.readFile(fileName, function(err, data){
      if (err) return reject(err);
      resolve(data);
    })
  })
}

const asyncReadFile = async function () {
  const f1 = await readFile('a.txt');
  const f2 = await readFile('b.txt');
  console.log(f1.toString());
  console.log(f2.toString());
};

asyncReadFile();

Функция readFile не имеет серьезных изменений по сравнению с первым методом.Функция Generator стала асинхронной функцией.Видно, что этот метод является лишь синтаксическим сахаром для первого метода.У асинхронной функции есть свой исполнитель!

Эта тема также может быть получена из более широкого использования yield , я напишу об этом в следующий раз, добро пожаловать, подписывайтесь на меня!