添加注解 var download = async blob fileName = let link = windowURLcreateObjectURLblob; const a = documentcreateElementa; adownload = $fileName; ahref = link; documentbodyappendChilda; a
// 定义一个名为download的异步函数,参数为blob和fileName
// 用window.URL.createObjectURL()方法创建一个URL对象
// 创建一个a标签,设置download属性为fileName,href属性为link,将a标签添加到body中
// 使用a.click()方法模拟点击a标签下载文件,完成后将a标签移除
// 使用window.URL.revokeObjectURL()方法释放URL对象的内存
var download = async (blob, fileName) => {
let link = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.download = ${fileName};
a.href = link;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(link);
};
// 定义一个名为safetyParse的函数,参数为str // 使用try...catch语句尝试将str转换成JSON对象,如果转换失败则返回null var safetyParse = (str) => { try { return JSON.parse(str); } catch (error) { return null; } };
// 定义一个名为getFile的异步函数,参数为url
// 使用fetch()方法获取url对应资源的响应对象res
// 使用res.body.getReader()方法获取一个ReadableStream对象的reader
// 使用res.headers.get()方法获取响应头中Content-Length字段的值,如果不存在则说明响应体没有长度限制,直接使用res.arrayBuffer()方法获取响应体的二进制数据
// 使用while循环不断从ReadableStream中读取数据,直到读取完毕
// 将每次读取的数据块存入chunks数组中,并累加receivedLength变量的值
// 返回一个Blob对象,该Blob对象包含所有读取到的数据块
var getFile = async (url) => {
const res = await fetch(url);
const reader = res.body.getReader();
const contentLength = +res.headers.get("Content-Length");
if (!contentLength) {
const data = await res.arrayBuffer();
return new Uint8Array(data);
}
let receivedLength = 0;
let chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
chunks.push(value);
receivedLength += value.length;
console.log(
fileSize: ${contentLength} %c downloaded ${receivedLength},
"background: #222; color: #bada55"
);
}
return new Blob(chunks);
};
// 定义一个名为getUrlsByM3u8的异步函数,参数为url和parser
// 使用URL()方法创建一个URL对象urlObj,将url中的pathname去掉最后一段,将search设为空字符串
// 将urlObj转换成字符串形式,得到base
// 使用fetch()方法获取url对应资源的响应对象res
// 使用res.text()方法获取响应体的文本数据data
// 将data按行切分成数组,过滤掉空行和以#开头的行
// 遍历剩下的行,如果parser存在则使用parser方法处理,否则根据行内容判断是绝对路径还是相对路径并拼接成完整的url
// 返回一个数组,包含所有处理过的url
var getUrlsByM3u8 = async (url, parser) => {
const urlObj = new URL(url);
urlObj.pathname = urlObj.pathname.split("/").slice(0, -1).join("/");
urlObj.search = "";
const base = urlObj.toString();
const res = await fetch(url);
const data = await res.text();
return data.split("\n").filter((i) => !!i && !i.startsWith("#")).map((i) => {
if (parser) {
return parser(i);
}
return i.startsWith("/") ? ${base}${i} : ${base}/${i};
});
};
// 定义一个名为getFiles的函数,参数为urls和max // 将urls数组中的每个元素添加一个index属性,值为该元素在数组中的下标 // 返回一个Promise对象,该Promise对象在所有请求完成后resolve一个数组,数组中包含所有请求返回的数据 // 先创建一个长度为max的空数组connections,表示同时允许max个请求在进行 // 再创建一个空数组files,用于存放所有请求返回的数据 // 使用for循环遍历urls数组,对于每个元素,将其添加到connections数组中 // 如果connections数组长度达到了max,说明已经有max个请求在进行,需要等待其中一个请求完成后再继续发起请求 // 这里使用Promise.race()方法返回一个Promise对象,当connections数组中有元素变成undefined时,说明对应的请求已经完成,这个Promise对象就resolve并返回该请求返回的数据 // 使用Promise.all()方法等待所有请求完成,并将所有请求返回的数据存入files数组中 // 最后返回files数组 var getFiles = (urls, max = 8) => { let connections = new Array(max); let files = []; urls = urls.map((i, index) => ({ ...i, index })); return new Promise((resolve) => { (async () => { for (let i = 0; i < urls.length; i++) { let url = urls[i]; connections.push(url); while (connections.length >= max) { const { index, response } = await Promise.race( connections.map((req, index) => ({ index, response: getFile(req.url) })) ); files[index] = response; connections[index] = undefined; } } await Promise.all( connections .filter((i) => i !== undefined) .map((req) => getFile(req.url)) ).then((responses) => { responses.forEach((response, index) => { const { index: i } = connections[index]; files[i] = response; }); }); resolve(files); })(); }); };
原文地址: https://www.cveoy.top/t/topic/bGNI 著作权归作者所有。请勿转载和采集!