function backgroundLoad ( ids, callback ) {
var i = 0;
function l ( ) {
if ( i < ids.length ) {
getArticleWithCache(ids[i ], function( a ){
backgroundLoad(a.children , l);
} else {
콜백()
}
}
수정된 backgroundLoad() 함수는 이전 함수와 매우 다르게 보이지만 구현하는 함수는 동일합니다. 이는 두 함수 모두 ID 배열을 매개변수로 받아들이고 배열의 각 요소에 대해 getArticleWithCache()를 호출한 다음 얻은 하위 기사 ID를 사용하여 backgroundLoad()를 재귀적으로 호출한다는 것을 의미합니다. 그러나 이전 프로그램에서는 for 루프 문으로 완료한 동일한 배열 순환 액세스를 식별하기 어렵습니다. 동일한 기능을 구현하는 두 가지 기능 세트가 왜 그렇게 다른가요?
이러한 차이점은 모든 함수가 getArticleWithCache()와 같이 서버와 통신해야 하는 상황이 발생한 후 즉시 반환해야 한다는 사실에서 비롯됩니다. 서버 응답을 받아야 하는 콜백 함수는 원래 함수가 실행되지 않는 한 호출할 수 없습니다. JavaScript를 사용하면 루프 중에 프로그램을 중단하고 for 문과 같이 나중에 이 중단점에서 실행을 다시 시작할 수 없습니다. 따라서 이 예제에서는 콜백 함수의 재귀 전달을 사용하여 기존 루프 문 대신 루프 구조를 구현합니다. CPS(Continuous Transfer Style)에 익숙한 사람들에게는 이것이 CPS의 수동 구현입니다. 루프 구문을 사용할 수 없기 때문에 앞서 언급한 트리 탐색과 같은 간단한 프로그램도 매우 복잡하게 작성해야 합니다. 이벤트 중심 프로그램 설계와 관련된 문제는 제어 흐름의 문제입니다. 루프 및 기타 제어 흐름 표현은 이해하기 어려울 수 있습니다.
또 다른 문제가 있습니다. 비동기 통신을 적용하지 않는 함수를 비동기 통신을 사용하는 함수로 변환하면 다시 작성된 함수에 새 매개변수로 콜백 함수가 필요하게 되는데, 이는 이미 기존 API에 있습니다. 내부 변경은 내부적으로 영향을 제한하지 않고 API와 다른 API 사용자의 전반적인 혼란을 초래하기 때문에 큰 문제를 야기합니다.
이러한 문제의 근본 원인은 무엇입니까? 예, 이러한 문제를 일으키는 것은 JavaScript의 단일 스레드 메커니즘입니다. 단일 스레드에서 비동기 통신을 수행하려면 이벤트 기반 프로그래밍과 복잡한 명령문이 필요합니다. 프로그램이 서버의 응답을 기다리는 동안 사용자 요청을 처리할 수 있는 다른 스레드가 있는 경우 위의 복잡한 기술은 필요하지 않습니다. <… 비동기 통신에. 이것은 JavaScript로 작성된 무료 소프트웨어 라이브러리입니다. 사용의 전제는 Mozilla Public License 및 GNU General Public License를 준수하는 것입니다. 해당 웹사이트에서 소스 코드를 다운로드할 수 있습니다.
지금 소스코드를 다운로드하여 사용해 보세요! 다운로드한 소스 코드를 Concurrent.Thread.js라는 폴더에 저장했다고 가정합니다. 작업을 수행하기 전에 다음 프로그램을 실행합니다.
코드 복사
코드는 다음과 같습니다. 이 프로그램을 실행하면 시작되는 숫자가 순차적으로 표시됩니다. 0부터 차례로 나타나며, 스크롤하여 보실 수 있습니다. 이제 코드를 자세히 살펴보겠습니다. 이는 결코 종료되지 않는 루프를 생성하기 위해 while(1) 조건을 사용합니다. 일반적으로 이와 같이 하나의 스레드만 계속 사용하는 JavaScript 프로그램은 브라우저가 정지되는 것처럼 보입니다. 동일하다면 당연히 스크롤이 허용되지 않습니다. 그러면 왜 위의 프로그램이 이것을 가능하게 합니까? 핵심은 while(1) 위의 Concurrent.Thread.create() 문입니다. 이는 이 라이브러리에서 제공하는 메서드로 새 스레드를 생성할 수 있습니다. 매개변수로 전달된 함수는 이 새 스레드에서 실행됩니다.
이 프로그램에는 숫자를 반복적으로 표시할 수 있는 새로운 함수 f()가 있습니다. 이 함수는 프로그램 세그먼트의 시작 부분에 정의되어 있으며 f()를 매개변수로 사용하여 create() 메서드가 두 번 호출됩니다. create() 메소드의 두 번째 매개변수는 변경되지 않고 f()에 전달됩니다. 이 프로그램을 실행하면 먼저 0부터 시작하는 일부 소수점, 100,000부터 시작하는 큰 숫자, 이전 소수점 순서를 따르는 숫자를 볼 수 있습니다. 프로그램이 소수와 큰 숫자를 번갈아 표시하는 것을 볼 수 있는데, 이는 두 개의 스레드가 동시에 실행되고 있음을 나타냅니다.
Concurrent.Thread의 또 다른 사용법을 보여드리겠습니다. 위의 예에서는 create() 메서드를 호출하여 새 스레드를 생성합니다. 라이브러리에서 API를 호출하지 않고도 이를 달성할 수 있습니다. 예를 들어 이전 예제는 다음과 같이 작성할 수 있습니다.
🎜>
in script 태그 내에는 단순히 자바스크립트로 무한 루프가 작성되어 있습니다. 태그에 유형 속성이 있음을 확인해야 합니다. (text/x-script.multithreaded-js) 이 속성이 스크립트 태그에 있으면 Concurrent.Thread가 새 스레드에 있습니다. 태그 사이의 프로그램. 이 경우와 마찬가지로 Concurrent.Thread 라이브러리가 포함되어야 한다는 점을 기억해야 합니다.
Concurrent.Thread를 사용하면 프로그램이 길고 연속성이 강한 경우에도 스레드 간 실행 환경을 자유롭게 전환할 수 있습니다. 이를 수행하는 방법에 대해 간략하게 논의할 수 있습니다. 즉, 코드 스위치가 필요합니다. 대략적으로 말하면 create()에 전달된 함수는 먼저 문자열로 변환된 다음 일괄적으로 실행될 수 있을 때까지 다시 작성됩니다. 그런 다음 이러한 프로그램은 스케줄러에 따라 단계별로 실행될 수 있습니다. 스케줄러는 여러 스레드를 조정하는 역할을 담당합니다. 즉, 수정된 모든 함수가 동일한 실행 기회를 갖도록 적절한 경우 조정할 수 있습니다. Concurrent.Thread는 실제로 새 스레드를 생성하지 않고 원래 단일 스레드를 기반으로 하는 다중 스레드 환경을 시뮬레이션합니다.
변환된 함수가 서로 다른 스레드에서 실행되는 것처럼 보이지만 실제로는 이 모든 작업을 수행하는 스레드가 하나뿐입니다. 변환된 기능 내에서 동기 통신을 수행하면 여전히 브라우저가 정지되며 이전 문제가 전혀 해결되지 않았다고 생각할 수도 있습니다. 그러나 걱정할 필요가 없습니다. Concurrent.Thread는 JavaScript의 비동기 통신 방법을 사용하여 구현된 사용자 정의 통신 라이브러리를 제공합니다. 이는 하나의 스레드가 서버의 응답을 기다리는 동안 다른 스레드가 실행될 수 있도록 설계되었습니다. 이 통신 라이브러리는 Concurrent.Thread.Http 아래에 있습니다. 사용법은 다음과 같습니다.
get() 메소드는 이름에서 알 수 있듯이 HTTP GET 메소드를 통해 얻을 수 있습니다. 대상 URL을 첫 번째 매개변수로 사용하고 HTTP 요청 헤더를 나타내는 배열을 선택적인 두 번째 매개변수로 사용하는 URL의 콘텐츠를 지정합니다. get() 메소드는 서버와 상호 작용하고 서버로부터 응답을 받은 후 XMLHttpRequest 객체를 반환 값으로 반환합니다. get() 메서드가 반환되면 서버 응답을 받은 것이므로 결과를 받기 위해 콜백 함수를 사용할 필요가 없습니다. 당연히 프로그램이 서버의 응답을 기다리는 동안 브라우저가 멈추는 것에 대해 더 이상 걱정할 필요가 없습니다. 또한 서버에 데이터를 보내는 데 사용할 수 있는 post() 메서드가 있습니다.