Netflix 인터뷰 질문이 어떻게 내 첫 번째 NPM 패키지로 바뀌었나요?
약속을 이해하지 못하는 문제
우리 모두 거기에 가본 적이 있어요. 우리는 각 항목에 대해 일종의 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

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

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

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

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

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

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

JavaScript는 현대 웹 개발의 핵심 언어이며 다양성과 유연성에 널리 사용됩니다. 1) 프론트 엔드 개발 : DOM 운영 및 최신 프레임 워크 (예 : React, Vue.js, Angular)를 통해 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축합니다. 2) 서버 측 개발 : Node.js는 비 차단 I/O 모델을 사용하여 높은 동시성 및 실시간 응용 프로그램을 처리합니다. 3) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.
