【问题标题】:Break down a code segment that uses some ES5 / advanced JavaScript methods of writing?分解使用一些 ES5 / 高级 JavaScript 编写方法的代码段?
【发布时间】:2019-06-07 02:06:31
【问题描述】:

有人可以解释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()
    ]);
}

【问题讨论】:

  • 您在哪里找到该代码?无论如何,它似乎不起作用 - 在该 exports 函数中缺少 Promise.all 调用
  • 所以您知道箭头函数是什么以及它是如何工作的,您知道map 是什么以及做什么?那么解构和对象字面量这行的哪一部分你不明白呢?
  • @Bergi 这是一个keystone应用程序,代码段来自link。我几乎迷路了,因为我对编程很陌生,这就是为什么我真的不知道东西去哪里了。是的,我学习了箭头函数和地图,但是将它们结合在一起让我很困惑。我也不熟悉解构和对象文字实践......

标签: javascript ecmascript-5 keystonejs


【解决方案1】:

涉及到一些 ES6 魔法:)

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

importdata 是一个数组。数组上的 map 函数所做的是获取数组中的每一项并对其应用一个函数,然后返回一个新数组,其中包含原始数组中的所有项,但已修改。 map function

在 ES6 中编写此代码的首选方式是使用 fat arrow function,即 .map((item) => ...,而不是编写 .map(function(item) { ... }

第三个魔法叫做destructuring assignment。它的作用是在这种情况下接受一个对象,并将 obj.name 和 obj.category 分配给两个新变量 name 和 category。我们可以在函数中使用这些变量,就好像我们使用两个单独的参数调用函数一样。

现在请记住,我们的 map 函数要求我们编写一个函数,该函数将数组项作为参数,并返回修改后的项。所以我们最终得到的是一个 map 函数,它遍历 importData 的参数,获取每个项目的名称和类别,并用它们调用另一个函数 createPost。 createPost 的结果是项目的新值,它全部被附加到一个与旧的大小相同的数组中,以及修改后的项目。

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

createPost 从每个项目中创建一个承诺。您可以阅读有关Promise here 的更多信息。 Promise 的 .then 方法将函数作为参数;当 promise 返回时调用(成功或错误)。 () => done() 只是一个粗箭头语法中的函数,它不接受任何参数并调用 done 函数。 .catch 也接受一个函数(done 是一个函数),并在 promise 返回错误时执行。注意。这样在成功和错误时都会调用 done 函数!

--不,这段代码不起作用,因为我们在第一行使用 importPromise 创建的实际上不是一个承诺,而是一个承诺数组!

祝你阅读顺利,正如 Beri 建议的那样,将代码翻译成 es5 以便继续学习可能是值得的。

【讨论】:

    【解决方案2】:

    我对 KeystoneJS 了解不多。无论如何,这是我的两分钱:

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

    importData 是一个 Array ,它包含一堆 Object 实例,每个实例都有一个 namecategory 键和 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)。然后,它尝试通过在其上映射createPost 函数,从模拟数据的所有“帖子”中创建一个Promise(并且-据我的理解-失败)。我认为它失败的原因是因为Array.prototype.map 没有返回Promise,它返回一个没有then 方法的新Array 实例(见下一行)。与其调用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 回调。

    【讨论】:

      【解决方案3】:

      https://babeljs.io/repl

      您可以使用此工具进行翻译。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-19
        • 1970-01-01
        • 2018-07-14
        • 2012-04-07
        • 2016-09-02
        • 1970-01-01
        • 2018-06-05
        • 1970-01-01
        相关资源
        最近更新 更多