简体   繁体   English

如何使用 javascript Map() 函数创建对象

[英]How to create object using javascript Map() function

I'm learning Map() function of javascript.我正在学习 javascript 的Map()函数。 I want to map rules for declarativeNetRequest but I need a bit of help.我想为declarativeNetRequest映射规则,但我需要一些帮助。

How I can create a map using this model as output:如何使用此模型作为输出创建地图

{
    "id" : 1,
    "priority": 1,
    "action" : { "type" : "block" },
    "condition" : {
        "urlFilter" : "abc",
        "domains" : ["foo.com"],
        "resourceTypes" : ["script"]
  }
}

At the moment I'm fetching a list of filters from a remote server and I'm parsing it using this code, after the parsing I want to map the results to have an object that I can use with declarativeNetrequest api目前,我正在从远程服务器获取过滤器列表,并使用此代码对其进行解析,解析后我想将结果映射到一个可以与declarativeNetrequest api 一起使用的对象

let def = {};
let out;
let defMap = new Map();

const fetch = async () => {
  await axios({
  url: "https://raw.githubusercontent.com/easylist/easylist/master/easylist/easylist_adservers.txt",
  responseType: "text"
  })
  .then( (response) => {
      let parsed = response.data.split("\n");
    out = parsed.filter( (item) => {
      if( !item.startsWith("!") ){
        return item.replace(/([\|\|\w\d\.\^]+)(?:[\w-\?=~,\$]+)$.*/, "$1");
      }
    });
  });
  return out;
}
// debug only 
fetch().then( (out) => {
  console.log(out);
});

will be this possible?这可能吗?

See below example that outputs a list of JSON objects based on the rules.请参阅下面的示例,该示例根据规则输出 JSON 对象列表。 Here are some other pointers:以下是其他一些提示:

  • You don't need a Map() , just a regular JSON/Javascript object structure您不需要Map() ,只需要一个常规的 JSON/Javascript 对象结构
  • You don't need to use .then() (Promises syntax) and await (async/await syntax) together - just chose one - await is the more modern way to deal with asynchronous responses - I used await您不需要同时使用.then() (Promises 语法)和 await(异步/等待语法)-只需选择一个-await 是处理异步响应的更现代的方法-我使用了 await
  • If you had used .then() , then the return statement would have completed before the inner callback function had been called, so out would not have been set如果您使用了.then() ,则 return 语句将在调用内部回调函数之前完成,因此不会设置out
  • I didn't look into the syntax of the file too much - but I presume fragments after ^ are useful, perhaps applying them to only certain subdomains我没有过多地研究文件的语法 - 但我认为 ^ 之后的片段很有用,也许只将它们应用于某些子域
  • The block rule accepts an array of domains - so you may be able to create one rule that applies to many domains instead of one rule for each domain阻止规则接受一组域 - 因此您可以创建一个适用于多个域的规则,而不是每个域的一个规则
import axios from 'axios'

async function fetch() {
  const resp = await axios({
    url: "https://raw.githubusercontent.com/easylist/easylist/master/easylist/easylist_adservers.txt",
    responseType: "text"
  })
  return [...parseDomains(resp.data)].map(blockRule)
}

function* parseDomains(data) {
  for (const line of data.split("\n")) {
    const match = line.match(/^[\|]+(?<domain>[^\^]+)/)
    if (match) yield match.groups.domain
  }
}

function blockRule(domain, id) {
  return {
    id,
    priority: 1,
    action: { type: "block" },
    condition: {
      urlFilter: `for_${domain}`,
      domains: [domain],
      resourceTypes: ["script"]
    }
  }
}

// debug only 
fetch().then((out) => {
  console.log(out)
})

Additional explanation:补充说明:

  1. Get the data:获取数据:
resp = await axios(...)
  1. parseDomains splits the data into lines (as you did before), and does a regular expression match on it. parseDomains将数据拆分为多行(如您之前所做的那样),并对其进行正则表达式匹配。 If it matches, it'll yield another domain.如果匹配,它将yield另一个域。 The function* makes this a generator expression - basically it can be iterated over (like an array) the elements are whatever you yield . function*使它成为一个生成器表达式 - 基本上它可以迭代(就像一个数组)元素是你yield任何东西。 If each line would yield a domain then you could have used .map() to convert each line to a domain, but only some lines yield domains so you need something else.如果每一行都会产生一个域,那么您可以使用.map()将每一行转换为一个域,但只有某些行会产生域,因此您需要其他东西。 An alternative would have been to create an empty array and then add a new domain element to it each time you found a valid domain.另一种方法是创建一个空数组,然后每次找到有效域时向其中添加一个新域元素。

The regular expression itself is a bit simpler than the one you had:正则表达式本身比您拥有的要简单一些:

  • match one or more |'s匹配一个或多个 | 的
  • followed by a one or more non-^ (so will end/terminate when ^ or end-of-string is encountered) - this is put into a match group (enclosed by parentheses, like you did) and given the name domain后跟一个或多个非 ^(因此将在遇到 ^ 或字符串结尾时结束/终止) - 将其放入匹配组(用括号括起来,就像您所做的那样)并给出名称domain
  • if the return value, match is truthy, it means you have found a match, and the matches can be found in match.groups - since I named it domain it's in match.groups.domain如果返回值match为真,则表示您找到了匹配项,并且可以在match.groups找到匹配match.groups - 因为我将其命名为domain所以它在match.groups.domain
  1. Since parseDomains is a generator expression, which are lazily evaluated, to run a map/filter on it you'll need to eagerly evaluate it - that's what [...expr] does - it basically forces the generator expression to be evaluated and converted into an array.由于parseDomains是一个生成器表达式,它是惰性求值的,要在其上运行映射/过滤器,您需要急切地求值它 - 这就是[...expr]所做的 - 它基本上强制对生成器表达式进行求值和转换成一个数组。 We could have kept evaluating things lazily like this instead:我们可以继续像这样懒惰地评估事情:
async function* fetch() {
  const resp = await axios(...)
  for (const domain of parseDomains(resp.data)
    yield blockRule(domain)
}
  1. Finally we map the domains through blockRule to output the actual rules, so you'll have an array of rule objects in the end.最后,我们通过 blockRule 映射域以输出实际规则,因此您最终将拥有一个规则对象数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM