Разбить фрагмент кода, который использует некоторые методы написания ES5 / Advanced JavaScript? - PullRequest
0 голосов
/ 12 января 2019

Может кто-нибудь объяснить часть в разделе exports, я, кажется, потерял и застрял на некоторое время. Начиная с importPromise. Кажется, что там много чего происходит, например, функции стрелок и метод карты. Я не могу видеть, откуда данные куда и куда поступают.

const keystone = require('keystone');
const PostCategory = keystone.list('PostCategory');
const Post = keystone.list('Post');

const importData = [
    { name: 'A draft post', category: 'Keystone JS' },
    ...
];

exports = function (done) {
    const importPromise = importData.map(({ name, category }) => createPost({ name, category }));

    importPromise.then(() => done()).catch(done);
};

const categories = {};

const createPost = ({ name, category }) => {
    let postCategory = new PostCategory.model({ category });
    if (categories[category]) {
        postCategory = categories[category];
    }
    categories[category] = postCategory;
    const post = new Post.model({ name });
    post.category = postCategory._id.toString();
    return Promise.all([
        post.save(),
        postCategory.save()
    ]);
}

Ответы [ 3 ]

0 голосов
/ 12 января 2019

Немного магии ES6:)

const importPromise = importData.map(({ name, category }) => createPost({ name, category }));

importdata - это массив. Функция map в массиве состоит в том, чтобы взять каждый элемент массива и применить к нему функцию, а затем вернуть новый массив со всеми элементами в исходном массиве, но с изменениями. функция карты

Вместо написания .map(function(item) { ... } предпочтительным способом написания этого в ES6 является функция жирной стрелки , т.е. .map((item) => ...

Третий бит магии называется деструктивное назначение . В этом случае он берет объект и назначает obj.name и obj.category двум новым переменным name и category. Мы можем использовать эти переменные внутри нашей функции, как если бы мы вызывали функцию с двумя отдельными аргументами.

Теперь помните, что наша функция карты требует, чтобы мы написали функцию, которая принимает элемент массива в качестве параметра и возвращает измененный элемент. Итак, в итоге мы получаем функцию карты, которая перебирает аргументы importData, беря имя и категорию каждого элемента и вызывая с ними другую функцию createPost. Результатом createPost является новое значение элемента, и все это добавляется к массиву того же размера, что и старый, с измененными элементами.

importPromise.then(() => done()).catch(done);

createPost создает обещание из каждого элемента. Вы можете прочитать больше о Promise здесь . Метод .then в Promise принимает функции в качестве аргумента; вызываться, когда обещание возвращается (либо с успехом, либо с ошибкой). () => done() - это просто функция с синтаксисом жирной стрелки, которая не принимает аргументов и вызывает функцию done. .catch также принимает функцию (done - функция) и выполняется, когда обещание возвращает ошибку. NB. таким образом, готовая функция вызывается как при успехе, так и при ошибке!

- и нет, этот код не будет работать, потому что то, что мы создаем в первой строке с помощью importPromise, на самом деле не обещание, а массив обещаний!

Удачи в чтении, и, как предполагает Бери, возможно, стоит перевести код на es5, чтобы следовать.

0 голосов
/ 12 января 2019

Я не знаю много о KeystoneJS. Во всяком случае, вот мои два цента:

const importData = [
  { name: 'A draft post', category: 'Keystone JS' },
  // ...
];

importData - это Array, который содержит набор Object экземпляров, каждый из которых имеет клавиши name и category со значениями String. Мне кажется, это какие-то «фиктивные данные», которые просто помещаются туда для целей тестирования.

Я переместил следующие части, потому что это делает код более понятным.

Эта часть:

const categories = {};

Мне кажется, что человек, который написал это, пытался реализовать какую-то форму "кеширования". Константа categories является простым «контейнером» для хранения сообщений, поэтому их можно использовать позже, а не создавать заново. Функция createPost раскрывает цель, если вы прочитаете ее.

const createPost = ({ name, category }) => {
    let postCategory = new PostCategory.model({ category });
    if (categories[category]) {
        postCategory = categories[category];
    }
    categories[category] = postCategory;
    const post = new Post.model({ name });
    post.category = postCategory._id.toString();
    return Promise.all([
        post.save(),
        postCategory.save()
    ]);
}

Кажется, что первый if использует конструкцию "кэширования" (const category), но то, как это происходит, немного сбивает с толку. Вот как бы я его рефакторинг:

const createPost = ({ name, category }) => {
    if (!categories[category]) {
        categories[category] = new PostCategory.model({ category });;
    }

    const post = new Post.model({ name });
    post.category = categories[category]._id.toString();

    return Promise.all([
        post.save(),
        categories[category].save()
    ]);
}

Наконец, для exports части:

Модуль экспортирует function, который ожидает обратного вызова в качестве аргумента (done). Затем он пытается создать Promise из всех «постов» фиктивных данных (и - насколько я понимаю - не удается), сопоставляя функцию createPost поверх него. Причина, по которой я думаю, что это не удается, заключается в том, что Array.prototype.map не возвращает Promise, он возвращает новый экземпляр Array, у которого нет метода then (см. Следующую строку). Вместо того, чтобы звонить then, он должен быть снова Promise.all. Когда это окончательное Promise успешно (или неуспешно) вызывается обратный вызов с результатом.

exports = function (done) {
    const importPromise = importData.map(({ name, category }) => createPost({ name, category }));

    importPromise.then(() => done()).catch(done);
};

Опять же, я бы переписал это так:

exports = function (done) {
    Promise.all(importData.map(createPost)).then(done).catch(done);
};

Или просто return окончательный Promise и избавление от done обратного вызова в целом.

0 голосов
/ 12 января 2019

https://babeljs.io/repl

Вы можете использовать этот инструмент для перевода.

...