약속을 이해하지 못하는 문제
우리 모두 거기에 가본 적이 있어요. 우리는 각 항목에 대해 일종의 API 요청을 해야 하는 대규모 데이터 세트를 가지고 있습니다. 장소 공급자를 가져오고 이 공급자 배열을 반환해야 하는 다양한 장소에 대한 ID 배열을 가정해 보겠습니다. 우리는 이러한 요청을 하기 위한 새로운 기능을 구축합니다...
const getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); for (let i = 0; i >= idArray.length - 1; i++) { const res = await fetch( `https://venues_for_me.org/venueid=${idArray[i]}` ); const venue = res.data; providers[i] = venue.provider; } return providers; };
앗, 요청을 모두 처리하기 위해 8년 전의 레거시 서버를 방금 도스했습니다...
우리 모두가 어느 시점에서 죄책감을 느꼈다고 생각하는 해결책은 일괄 요청 사이에 몇 밀리초의 시간 제한을 설정하는 것입니다...
const getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); const batchSize = 50; for (let i = 0; i >= idArray.length - 1; i++) { const batchToExecute = Array(batchSize); for (let y = 1; i >= batchSize; i++) { batchToExecute[i] = fetch( `https://venues_for_me.org/venue?id=${idArray[i]}`, ); await (async () => setTimeout(() => {}, 200))(); } const responses = await Promise.all(batchToExecute); responses.forEach((venue) => { providers[i] = venue.provider; }); } return providers; };
이 예제를 작성한 후 샤워를 하고 싶습니다... 동일한 배열(또는 지저분한 코드)의 엄청나게 많은 중복은 말할 것도 없고; 이는 임의의 시간 초과를 설정하여 실행 속도를 인위적으로 제한하는 것입니다
여기서 좋은 대답은 최대 동시성에 공간이 있을 때만 Promise를 생성하는 동시성 제한기를 만드는 것입니다. 다음과 유사한 것:
getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); const batchSize = 50; for (let i = 0; i >= idArray.length - 1; i++) { const batchToExecute = Array(batchSize); for (let y = 1; i >= batchSize; i++) { batchToExecute[i] = fetch( `https://venues_for_me.org/venue?id=${idArray[i]}`, ); await (async () => setTimeout(() => {}, 200))(); } const responses = await Promise.all(batchToExecute); responses.forEach((venue) => { providers[i] = venue.provider; }); } return providers; };
보시다시피 약속을 잃지 않으려면 요청의 백로그를 유지하는 일종의 대기열을 구현해야 합니다. 이 기사의 제목이 나옵니다.
더닝 크루거
The Primagen의 영상을 보다가 특정 부분이 눈에 들어왔습니다. Netflix 인터뷰에서 그가 가장 좋아하는 질문 중 하나는 인터뷰 대상자가 비동기 대기열을 만들고 약속을 실행하기 위한 최대 동시성을 생성하는 것입니다.
이것은 제가 겪었던 위의 문제와 정확히 같습니다!
이 인터뷰 질문은 여러 겹으로 구성되어 있습니다. 대기열이 구현된 후 오류에 대한 재시도를 구현합니다.
나는 이 도전에 오후를 보냈고 기술 문제가 있다는 것을 매우 빨리 배웠습니다. 알고 보니 저는 약속을 생각만큼 잘 몰랐습니다.
Promise에 대해 며칠 동안 심층 분석한 후 컨트롤러, 맵, 세트, 약한 맵 및 세트를 중단하십시오. 비동기화를 만들었습니다
Asyncrify를 사용한 내 목표는 간단했습니다. 또 다른 비동기 대기열을 만듭니다. 그러나 외부 종속성이 없으며 가능한 한 리소스가 가볍습니다.
대기열에 기능을 추가하고 최대 동시성을 설정할 수 있어야 했습니다. 시간 초과를 설정 및 처리하고 기하급수적으로 감소하는 재시도를 활성화 및 비활성화합니다.
실력 문제다
그럼 묻지 않은 기술 문제는 무엇이었나요?
약속을 배우세요 아무리 강조해도 지나치지 않습니다.
내가 직면한 첫 번째 문제 중 하나는 약속 실행이 어떻게 작동하는지 이해하지 못했다는 것입니다. 첫 번째 구현은 다음과 같습니다.
const getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); for (let i = 0; i >= idArray.length - 1; i++) { const res = await fetch( `https://venues_for_me.org/venueid=${idArray[i]}` ); const venue = res.data; providers[i] = venue.provider; } return providers; };
문제를 즉시 확인하셨으리라 믿습니다. Promise.race를 사용하여 "최대 동시" 약속을 동시에 실행하고 있습니다.
하지만 이는 첫 번째 Promise가 해결된 후에만 계속됩니다. 나머지는 무시됩니다. 그런 다음 1개를 더 추가하고 다시 실행합니다.
기본으로 돌아가야 했습니다.
해결책은 대신 .then 및 .catch를 사용하고 현재 실행 중인 섹션에 열려 있는 자리가 있을 때만 기능을 실행하는 것입니다.
const getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); const batchSize = 50; for (let i = 0; i >= idArray.length - 1; i++) { const batchToExecute = Array(batchSize); for (let y = 1; i >= batchSize; i++) { batchToExecute[i] = fetch( `https://venues_for_me.org/venue?id=${idArray[i]}`, ); await (async () => setTimeout(() => {}, 200))(); } const responses = await Promise.all(batchToExecute); responses.forEach((venue) => { providers[i] = venue.provider; }); } return providers; };
이제 우리는 동시 Promise를 훨씬 더 잘 추적할 뿐만 아니라 사용자가 원하는 방식으로 오류와 해결 방법을 처리할 수도 있습니다.
중단 컨트롤러를 사용하세요 제가 자주 보는 큰 실수 중 하나는 약속이 초기화된 후 더 이상 필요하지 않을 때 사람들이 중단 컨트롤러를 사용하지 않는다는 것입니다. 나도 이것을했다.
처음에는 타임아웃을 하기 위해 Promise.race를 사용했습니다
getProvidersFromVenueIDs = async (idArray) => { const providers = Array(idArray.length); const batchSize = 50; for (let i = 0; i >= idArray.length - 1; i++) { const batchToExecute = Array(batchSize); for (let y = 1; i >= batchSize; i++) { batchToExecute[i] = fetch( `https://venues_for_me.org/venue?id=${idArray[i]}`, ); await (async () => setTimeout(() => {}, 200))(); } const responses = await Promise.all(batchToExecute); responses.forEach((venue) => { providers[i] = venue.provider; }); } return providers; };
상상하시는 대로죠. 약속은 시간 초과 후에도 계속 실행됩니다. 그냥 무시됐네요. 이것은 대기열을 구현한 첫 번째 실수와 많이 비슷해 보이지 않습니까?
중단 컨트롤러에 대한 나의 유일한 경험은 반응에 불과했기 때문에 나는 중단 컨트롤러에 대해 약간의 연구를 수행했습니다.
AbortSignal.timeout!! 이게 바로 제가 하고 싶었던 일이에요!
내 코드에 대한 유일한 업데이트는 한 줄이었습니다
async #runTasksRecursively() { await this.#runAsync(); if (this.#queue.size === 0 && this.#retries.length === 0) { return; } this.#addToPromiseBlock(); } async #runAsync() { if (!this.#runningBlock.every((item) => item === undefined)) { await Promise.race(this.#runningBlock); } } #addToPromiseBlock() { const emptyspot = this.#getEmptySpot(); if (this.#retries.length > 0 && !this.#lastRunWasError) { console.log(this.#retries); if (this.#errorsToInject.size > 0) { const task = this.#popInSet(this.#errorsToInject); if (this.#queue.size !== 0) { this.#lastRunWasError = true; } this.#assignPromisToExecutionArray(task, emptyspot); } } else { const task = this.#popInSet(this.#queue); this.#lastRunWasError = false; this.#assignPromisToExecutionArray(task, emptyspot); } }
와우 정말 쉬웠어요! 하지만 이제 패키지 사용자는 시간 초과 기능을 사용하기 위해 상용구를 만들어야 합니다. 두려워할 필요가 없습니다! 내가 당신을 위해 그랬어요!
add(fn, callback, errCallback) { if (this.#maxConcurrency !== 0 && this.#running >= this.#maxConcurrency) { this.#queue.add(fn); } else { this.#running++; fn() .then(callback) .catch(errCallback) .finally(() => { this.#running--; if (this.#queue.size > 0) { const nextPromise = this.#queue.values().next().value; this.#queue.delete(nextPromise); this.add(nextPromise, callback, errorCallback); } }); } }
또 다른 마이크로 NPM 패키지
그럼 비동기화는 어떻게 사용하나요?
정말 쉽습니다. 먼저 대기열을 만듭니다.
#promiseBuilder(fn) { const promise = new Array(this.#promiseTimeout > 0 ? 2 : 1); promise[0] = fn(); if (this.#promiseTimeout > 0) { promise[1] = this.#timeoutHandler(); } return promise; } #promiseRunner(fn, callback) { const promise = this.#promiseBuilder(fn); Promise.race(promise) .then((res) => { callback(res, null); }) .catch((err) => { this.#errorHandler(err, fn, callback); }) .finally(() => { this.#running--; this.#runPromiseFromQueue(callback); }); }
대기열은 기본적으로 시간 초과나 폐기가 없으며 최대 동시 실행도 없습니다.
생성자에 구성 obj를 제공할 수도 있습니다.
const promise = fn( this.#timeout > 0 ? AbortSignal.timeout(this.#timeout) : null, );
큐에 Promise를 추가하려면 이를 반환하는 함수로 래핑해야 합니다.
export const abortHandler = (signal, reject) => { if (signal.aborted) { return reject(new Error("Aborted")); } const abortHandler = () => { reject(new Error("Aborted")); signal.removeEventListener("abort", abortHandler); }; signal.addEventListener("abort", abortHandler); };
타임아웃 기능을 사용하려면 중단 핸들러를 추가하는 것을 잊지 마세요!
그런 다음 콜백 및 오류 콜백과 함께 add 메소드에 함수를 전달하기만 하면 됩니다
import Queue from 'Asyncrify' const queue = new Queue()
추가하면 끝입니다! 원하는 만큼 빠르게 추가하세요. 모두 완료될 때까지 한 번에 3개만 실행됩니다!
저는 이 패키지를 만들면서 많은 것을 배웠습니다. 내가 틀림없이 오래 전에 알았어야 했던 것들. 그래서 내가 이 글을 쓰고 있는 것이다. 저는 여러분이 제가 저지른 어리석은 실수를 보고, 어리석은 실수를 저지르고 그 실수로부터 배울 수 있는 용기를 느끼기를 바랍니다. 그런 일이 발생하면 당황하지 말고 대피하세요.
나가서 기사를 써보세요. 봇에서 매주 10개의 다운로드가 포함된 마이크로 패키지를 만듭니다. 결국에는 필요한지 전혀 몰랐던 것들을 배우게 될 것입니다
위 내용은 Netflix 인터뷰 질문이 어떻게 내 첫 번째 NPM 패키지로 바뀌었나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

파이썬과 자바 스크립트는 각각 고유 한 장점이 있으며 선택은 프로젝트 요구와 개인 선호도에 따라 다릅니다. 1. Python은 간결한 구문으로 데이터 과학 및 백엔드 개발에 적합하지만 실행 속도가 느립니다. 2. JavaScript는 프론트 엔드 개발의 모든 곳에 있으며 강력한 비동기 프로그래밍 기능을 가지고 있습니다. node.js는 풀 스택 개발에 적합하지만 구문은 복잡하고 오류가 발생할 수 있습니다.

javaScriptisNotBuiltoncorc; it'SangretedLanguageThatrunsonOngineStenWrittenInc .1) javaScriptWasDesignEdasAlightweight, 해석 hanguageforwebbrowsers.2) Endinesevolvedfromsimpleplemporectreterstoccilpilers, 전기적으로 개선된다.

JavaScript는 프론트 엔드 및 백엔드 개발에 사용할 수 있습니다. 프론트 엔드는 DOM 작업을 통해 사용자 경험을 향상시키고 백엔드는 Node.js를 통해 서버 작업을 처리합니다. 1. 프론트 엔드 예 : 웹 페이지 텍스트의 내용을 변경하십시오. 2. 백엔드 예제 : node.js 서버를 만듭니다.

Python 또는 JavaScript는 경력 개발, 학습 곡선 및 생태계를 기반으로해야합니다. 1) 경력 개발 : Python은 데이터 과학 및 백엔드 개발에 적합한 반면 JavaScript는 프론트 엔드 및 풀 스택 개발에 적합합니다. 2) 학습 곡선 : Python 구문은 간결하며 초보자에게 적합합니다. JavaScript Syntax는 유연합니다. 3) 생태계 : Python에는 풍부한 과학 컴퓨팅 라이브러리가 있으며 JavaScript는 강력한 프론트 엔드 프레임 워크를 가지고 있습니다.

JavaScript 프레임 워크의 힘은 개발 단순화, 사용자 경험 및 응용 프로그램 성능을 향상시키는 데 있습니다. 프레임 워크를 선택할 때 : 1. 프로젝트 규모와 복잡성, 2. 팀 경험, 3. 생태계 및 커뮤니티 지원.

서론 나는 당신이 이상하다는 것을 알고 있습니다. JavaScript, C 및 Browser는 정확히 무엇을해야합니까? 그들은 관련이없는 것처럼 보이지만 실제로는 현대 웹 개발에서 매우 중요한 역할을합니다. 오늘 우리는이 세 가지 사이의 밀접한 관계에 대해 논의 할 것입니다. 이 기사를 통해 브라우저에서 JavaScript가 어떻게 실행되는지, 브라우저 엔진의 C 역할 및 웹 페이지의 렌더링 및 상호 작용을 유도하기 위해 함께 작동하는 방법을 알게됩니다. 우리는 모두 JavaScript와 브라우저의 관계를 알고 있습니다. JavaScript는 프론트 엔드 개발의 핵심 언어입니다. 브라우저에서 직접 실행되므로 웹 페이지를 생생하고 흥미롭게 만듭니다. 왜 Javascr

Node.js는 크림 덕분에 효율적인 I/O에서 탁월합니다. 스트림은 메모리 오버로드를 피하고 큰 파일, 네트워크 작업 및 실시간 애플리케이션을위한 메모리 과부하를 피하기 위해 데이터를 점차적으로 처리합니다. 스트림을 TypeScript의 유형 안전과 결합하면 Powe가 생성됩니다

파이썬과 자바 스크립트 간의 성능과 효율성의 차이는 주로 다음과 같이 반영됩니다. 1) 해석 된 언어로서, 파이썬은 느리게 실행되지만 개발 효율이 높고 빠른 프로토 타입 개발에 적합합니다. 2) JavaScript는 브라우저의 단일 스레드로 제한되지만 멀티 스레딩 및 비동기 I/O는 Node.js의 성능을 향상시키는 데 사용될 수 있으며 실제 프로젝트에서는 이점이 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전

Dreamweaver Mac版
시각적 웹 개발 도구

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.