干掉JavaScript

时间:2018-10-21 14:23:59

标签: javascript node.js ajax gulp xmlhttprequest

我要多次调用服务器,并通过gulpfile中的API以yaml格式创建页面和帖子。这些功能看起来足够相似,我可以为所有这些功能制作一个功能。

我很难为每个项目创建对象,因为jsonObj不能在XMLHttpRequest之外定义

这是我的代码:

function collectLoop(slug, tempDir, destDir, args) {
  const newObject = args;
  fs.writeFile(`${tempDir}${slug}.json`,
  JSON.stringify(newObject), function (err) {
    if (err) throw err;
  });
  gulp.src(`${tempDir}${slug}.json`)
    .pipe(jsonToYaml({ safe: true}))
    .pipe(gulp.dest(destDir));
};


/*********************************************************************/
/******************************* PAGES *******************************/
/*********************************************************************/

function pageCollection(url, tempDir, destDir) {
  const xhr = new XMLHttpRequest();
  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      const jsonObj = JSON.parse(xhr.responseText);
      checkDir(tempDir);
      checkDir(destDir);
      for (let i = 0; i < jsonObj.length; i += 1) {
        let hero_heading = false;
        let hero_subheading = false;

        if(jsonObj[i].acf.hero != undefined) {
          hero_heading = jsonObj[i].acf.hero.heading;
          hero_subheading = jsonObj[i].acf.hero.subheading;
        }
        collectLoop(jsonObj[i].slug, tempDir, destDir, {
          "obj_id" : jsonObj[i].id,
          "title" : jsonObj[i].title.rendered,
          "slug" : jsonObj[i].slug,
          "modified" : jsonObj[i].modified,
          "featured_image" : {
            "large" : jsonObj[i]._embedded['wp:featuredmedia'][0].source_url,
            "small" : jsonObj[i]._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url,
          },
          "settings" : {
            "contact_box" : jsonObj[i].acf.contact_box,
            "footer_map" : jsonObj[i].acf.map,
            "hero_banner" : jsonObj[i].acf.hero_banner,
          },
          "hero" : {
            "heading" : hero_heading,
            "subheading" : hero_subheading,
          },
          "contact_form" : jsonObj[i].acf.contact_form,
          "excerpt" : jsonObj[i].acf.excerpt,
          "content" : jsonObj[i].content.rendered,
        });
      }
    }
  };
  xhr.open('GET', url);
  xhr.send();
}

/*********************************************************************/
/******************************* POSTS *******************************/
/*********************************************************************/

function postCollection(url, tempDir, destDir) {
  const xhr = new XMLHttpRequest();
  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      const jsonObj = JSON.parse(xhr.responseText);
      checkDir(tempDir);
      checkDir(destDir);
      for (let i = 0; i < jsonObj.length; i += 1) {
        collectLoop(jsonObj[i].slug, tempDir, destDir, {
          "obj_id" : jsonObj[i].id,
          "title" : jsonObj[i].title.rendered,
          "slug" : jsonObj[i].slug,
          "date" : jsonObj[i].date,
          "modified" : jsonObj[i].modified,
          "featured_image" : {
            "large" : jsonObj[i]._embedded['wp:featuredmedia'][0].source_url,
            "small" : jsonObj[i]._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url,
          },
          "excerpt" : jsonObj[i].excerpt.rendered,
          "content" : jsonObj[i].content.rendered,
        });
      }
    }
  };
  xhr.open('GET', url);
  xhr.send();
}

1 个答案:

答案 0 :(得分:0)

这可能应该发布在https://codereview.stackexchange.com中,而不是在stackoverflow上发布。但是我还是要尝试回答这个问题

您可以创建一个Functions that return a function

这可能是我会做的。

  • 使用fetch代替XMLHttpRequest
  • 使用async/await避免发生回调地狱
  • 使用for..of循环来始终避免jsonObj[i]
  • 使用Object.assign来获取您在所有请求中执行的默认对象,并使用映射fn返回的对象

(PS:未经测试)

function collectLoop(slug, tempDir, destDir, args) {
  const newObject = args
  const file = `${tempDir}${slug}.json`

  fs.writeFile(file, JSON.stringify(newObject), err => {
    if (err) throw err
  })

  gulp.src(file)
    .pipe(jsonToYaml({ safe: true }))
    .pipe(gulp.dest(destDir))
}

// Get is a function that returns another function
const get = (() => {
  async function get (map, url, tempDir, destDir) {
    const res = await fetch(url)
    const jsonObj = await res.json()

    checkDir(tempDir)
    checkDir(destDir)

    for (let item of jsonObj) {
      // Default for everything
      collectLoop(item.slug, tempDir, destDir, Object.assign({
        obj_id: item.id,
        title: item.title.rendered,
        slug: item.slug,
        date: item.date,
        modified: item.modified,
        featured_image: {
          large: item._embedded['wp:featuredmedia'][0].source_url,
          small: item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url,
        },
        excerpt: item.excerpt.rendered,
        content: item.content.rendered
      }, map(jsonObj)))
    }
  }

  return (map = () => {}) => (...args) => get(map, ...args)
})()


const postCollection = get() // no mapping needed, dose the default
const pageCollection = get(item => ({ // This is our mapping fn
  settings: {
    contact_box: item.acf.contact_box,
    footer_map: item.acf.map,
    hero_banner: item.acf.hero_banner,
  },
  hero: {
    heading: item.acf.hero ? item.acf.hero.heading : false,
    subheading: item.acf.hero ? item.acf.hero.subheading : false
  },
  contact_form: item.acf.contact_form
}))