const url = "https://i.imgur.com/sduLRvf.jpeg";
const resp = await fetch(url);
const blob = await resp.blob();
const name = url.split("/").pop().replace("jpeg", "jpg");
downloadBlob(blob, name, url);
function downloadBlob(blob, name, url) {
const anchor = document.createElement("a");
anchor.setAttribute("download", name || "");
const blobUrl = URL.createObjectURL(blob);
anchor.href = blobUrl + (url ? ("#" + url) : "");
anchor.click();
setTimeout(() => URL.revokeObjectURL(blobUrl), 3000);
}url параметр опциональный, чисто чтобы сохранить возможность посмотреть оригинальный URL в менеджере загрузок. console.log((Buffer.from(hex, "hex").toString("utf-8")));5MA0C��@�Q[...new TextEncoder().encode("5MA0C��@�Q")].map(n => n.toString(16)).join("")
===
"354d413043efbfbdefbfbd40efbfbd51"
// true function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}for (let i = 0; i < 10; i++) {
console.log(i);
await sleep(100);
}
await sleep(1000);
console.log("Done");"Done". TransformStream. ReadableStream. Единственное отличие, что TransformStream "ленивый". Т.е. если закомментировать await newResponse.blob(); onProgress не будет вызываться, хотя данные были загружены.const response = await fetch("https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg");
total.value = parseInt(response.headers.get("content-length")) || 0;
function onProgress(chunk) {
loaded.value += chunk.length;
}
const ts = new TransformStream({
transform(chunk, controller) {
onProgress(chunk);
controller.enqueue(chunk);
},
});
response.body.pipeThrough(ts);
const newResponse = new Response(ts.readable);
const blob = await newResponse.blob();"content-length" может отсутствовать. "content-encoding", который, к слову, по-умолчанию будет недоступен для кода при кросс-доменных запросах."content-encoding" в "content-length" значение всегда указано для сжатого респонса, а в коллбеке будут уже не сжатые данные. Т.е. loaded в таком случае будет больше значения total ("content-length")ReadableStream:const reader = response.body.getReader();
const readableStream = new ReadableStream({
async start(controller) {
while (true) {
const {done, value} = await reader.read();
if (done) { break; }
onProgress(value);
controller.enqueue(value);
}
controller.close();
reader.releaseLock();
},
cancel() {
void reader.cancel();
}
});
const newResponse = new Response(readableStream); function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}const btns = [...document.querySelectorAll("button")];
const filteredBtns = btns.filter(btn => btn.textContent.startsWith("Кнопка"));
for (const btn of filteredBtns) {
btn.click();
await sleep(5000);
} {name: 'Ivan'}
new Uint8Array(100_000_000). Весомый.let weakMap = new WeakMap();
let obj = {a: new Uint8Array(100_000_000)};
weakMap.set({}, obj);WeakMap Map.new Uint8Array(1_000_000_000).let weakMap = new Map(); не поможет при таком спаме в консоль, т.к. если объект выведен в косколь, он так и будет висеть в памяти, пока консоль не будет очищена (console.clear()), либо страница перезагружена.
WeakHashMap. onerror у img элемента.<img src="not-loading-image.jpg" onerror="this.remove();">
<img src="https://hsto.org/webt/62/a8/df/62a8df7d29053796257182.png" onload="console.log(this);"> async asyncMethod() {
// следующее добавит в очередь микро-тасков:
await null; // или
await Promise.resolve();
// а это добавит в очередь тасков:
await new Promise(resolve => setTimeout(resolve));
// лучше используй setImmediate, он многократно быстрее отработает (без задержки в 4 мс)
console.log("hello from asyncMethod");
}async) функции или коллбека конструтора Promise выполняется синхронно до первого await.await, не используй async.export default {
data() {
return {
dateNow: new Date(),
timerId: null
};
},
mounted() {
this.timerId = setInterval(() => {
this.dateNow = new Date();
}, 1000);
},
beforeUnmount() {
clearInterval(this.timerId);
}
};import {ref, onUnmounted} from "vue";
const dateNow = ref(new Date());
const timerId = setInterval(() => {
dateNow.value = new Date();
}, 1000);
onUnmounted(() => {
clearInterval(timerId);
}); // element-util.js
export function createElement(options) {
// код функции
}
export function showElement(options) {
// код функции
}
export function hideElement(options) {
// код функции
}import {createElement} from "./element-util.js";
function Component() {
const heading = createElement({
id: "heading",
content: "Hello World",
});
const message = createElement({
id: "message",
content: "New Article",
});
return {heading, message};
} requests использует по-умолчанию (даже без использования Session), а именно наличию connection: "keep-alive", keep alive режим работает из коробки, и, очевидно, правильно.node-fetch нет. Но это можно исправить, см. мой ответ."authority", "method", "path", "scheme".":authority", ":method", ":path", ":scheme", псевдо-заголовки HTTP/2.requests — HTTP/1.1 библиотека.import fetch from "node-fetch";
import http from "node:http";
import https from "node:https";
const httpAgent = new http.Agent({keepAlive: true});
const httpsAgent = new https.Agent({keepAlive: true});
function agent(_parsedURL) {
if (_parsedURL.protocol === "http:") {
return httpAgent;
} else {
return httpsAgent;
}
}
const response = await fetch("https://example.com/", {
agent
}); function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}while (true) {
await sleep(10000);
openBox();
await sleep(3000);
const data = JSON.parse(response);
for (const entry of data) {
entry.btn.click(); // рили?
await sleep(3000);
entry.btnClose.click();
}
await sleep(3000);
btn.click();
} Ну почему-то, после перезагрузки страницы...
append, after, createElement.querySelector также пригодится для уже существующих нод. Spread types may only be created from object types.
undefined.useSomething) делается так — возвращается объект, чьи поля присваиваются другому объкту путем оператора спреад.