비동기 요청을 하는 함수 foo
에서 응답/결과를 반환하는 방법은 무엇입니까?
콜백에서 값을 반환하고 결과를 함수 내부의 로컬 변수에 할당하고 해당 변수를 반환하려고 시도했지만 이러한 메서드 중 어느 것도 실제로 응답을 반환하지 않습니다. 모두 초기 값으로 undefined
或其他变量 result
을 반환합니다.
콜백을 허용하는 비동기 함수의 예(jQuery의 ajax
함수 사용):
Node.js를 사용한 예:
으아악 then
promise 블록을 사용한 예:
코드에 jQuery를 사용하지 않는다면 이 답변이 도움이 될 것입니다
코드는 다음과 같아야 합니다:으아악
Felix Kling은 AJAX용 jQuery를 사용하는 사람들을 위한 답변을 훌륭하게 작성했지만, 저는 jQuery를 사용하지 않는 사람들을 위해 대안을 제공하기로 결정했습니다. (
참고: 새로운API인 Angular 또는 Promise를 사용하는 경우 아래에 다른 답변을 추가했습니다 )
당신이 직면한 문제fetch
다음은 다른 답변의 "질문 설명"에 대한 간략한 요약입니다. 이 내용을 읽은 후 확실하지 않은 경우 해당 답변을 읽어보시기 바랍니다.
AJAX의
A는 asynchronous을 의미합니다. 이는 요청 전송(또는 응답 수신)이 일반적인 실행 흐름에서 제거됨을 의미합니다. 귀하의 예에서
.send code>
는 즉시 반환되고 다음 문return result;
는success
콜백으로 전달한 함수를 호출하기 전에 실행됩니다. .코드>..send code>
立即返回,并且在调用您作为success
回调传递的函数之前执行下一条语句return result;
이것은 반환할 때 정의한 리스너가 아직 실행되지 않았음을 의미하며, 이는 반환한 값이 아직 정의되지 않았음을 의미합니다.다음은 간단한 비유입니다.
으아악 (바이올린)때문에
. AJAX는 서버가 브라우저에 값이 무엇인지 알려주기 전에 값을 반환하는 방식으로 작동합니다.a=5
部分尚未执行,因此返回的a
值为undefined
이 문제에 대한 한 가지 가능한 해결책은 계산이 완료된 후 프로그램에 무엇을 해야 하는지 알려주는 코드를작성하는 것입니다. 으아악 이것을
CPS라고 합니다. 기본적으로 우리는 완료 시 수행할 작업을 전달하고 이벤트가 완료될 때 반응하는 방법(예: AJAX 호출 또는 이 경우 시간 초과)을 코드에 알려줍니다.
getFive
사용법: 으아악화면에 "5"가 나타납니다.
(바이올린). 가능한 해결책
이 문제를 해결하는 방법에는 기본적으로 두 가지가 있습니다.
동기식 AJAX의 경우
하지 마세요!Felix의 답변은 이것이 왜 나쁜 생각인지에 대한 몇 가지 설득력 있는 주장을 제시합니다. 전체적으로 서버가 응답을 반환하고 매우 나쁜 사용자 경험을 생성할 때까지 사용자의 브라우저를 정지시킵니다. 이유를 설명하는 MDN의 또 다른 빠른 요약은 다음과 같습니다.
이 작업을 해야 한다면 깃발을 전달할 수 있습니다. 구체적인 방법은 다음과 같습니다:
으아아아2. 코드 재구성
함수가 콜백을 허용하도록 만드세요. 예제 코드에서는
foo
接受回调。我们将告诉代码当foo
가 완료되었을 때 가 어떻게 반응하는지 알 수 있습니다.그래서:
으아아아는 다음과 같이 됩니다:
으아아아여기에서는 익명 함수를 전달하지만 기존 함수에 대한 참조도 쉽게 전달하여 다음과 같이 만들 수 있습니다.
으아아아이러한 유형의 콜백 디자인을 수행하는 방법에 대한 자세한 내용은 Felix의 답변을 확인하세요.
이제 그에 따라 동작하도록 foo 자체를 정의해 보겠습니다
으아아아(바이올린)
이제 AJAX가 성공적으로 완료되면 실행할 작업을 허용하는 foo 함수가 생겼습니다. 응답 상태가 200이 아닌지 확인하고 적절한 조치(실패 처리기 생성 등)를 수행하여 이 기능을 더욱 확장할 수 있습니다. 그것은 우리의 문제를 효과적으로 해결했습니다.
이 내용을 여전히 이해하는 데 어려움이 있다면 AJAX에서 MDN 시작 가이드를 읽어보세요.
질문
Ajax의 A는 asynchronous을 의미합니다. 이는 요청 전송(또는 응답 수신)이 일반적인 실행 흐름에서 제거됨을 의미합니다. 귀하의 예에서는
$.ajax
立即返回,并且下一条语句return result;
在您作为success
함수가 호출되기 전에 콜백이 전달됩니다.다음은 동기 스트림과 비동기 스트림의 차이를 더 명확하게 만드는 비유입니다.
동기화
친구에게 전화를 걸어 정보를 찾아달라고 부탁한다고 상상해 보세요. 시간이 좀 걸릴 수도 있지만, 친구가 필요한 대답을 할 때까지 전화 옆에서 허공을 바라보며 기다립니다.
"일반" 코드가 포함된 함수를 호출할 때도 같은 일이 발생합니다.
으아아아하지만
findItem
可能需要很长时间才能执行,但var item = findItem();
이후의 모든 코드는 함수가 결과를 반환할 때까지 대기해야 합니다.비동기
같은 이유로 친구에게 다시 전화를 겁니다. 하지만 이번에는 당신이 그에게 당신이 불안하다고 말하면 그는 당신의 휴대폰을 사용하여 당신에게 다시 전화해야 합니다. 전화를 끊고 집을 떠나 계획했던 일을 합니다. 친구가 다시 전화하면 귀하는 그가 제공한 정보를 처리하는 것입니다.
Ajax 요청을 하면 바로 이런 일이 발생합니다.
으아아아응답을 기다리지 않고 즉시 실행을 계속하며 Ajax 호출 후 명령문을 실행합니다. 최종적으로 응답을 받으려면 응답을 받은 후 호출되는 함수인 콜백(알고 계시나요? 콜백?)을 제공해야 합니다. 이 호출 이후의 모든 문은 콜백이 호출되기 전에 실행됩니다.
솔루션
JavaScript의 비동기 특성을 수용하세요! 일부 비동기 작업은 동기 작업을 제공하지만("Ajax"와 마찬가지로) 일반적으로 사용이 권장되지 않으며 특히 브라우저 컨텍스트에서는 더욱 그렇습니다.
왜 나쁜가요?
JavaScript는 브라우저의 UI 스레드에서 실행되며 장기 실행 프로세스는 UI를 잠가서 응답하지 않게 만들 수 있습니다. 또한 JavaScript 실행 시간에는 상한이 있으며 브라우저는 사용자에게 실행을 계속할지 여부를 묻습니다.
이 모든 것은 매우 나쁜 사용자 경험으로 이어집니다. 사용자는 모든 것이 제대로 작동하는지 알 수 없습니다. 또한 인터넷 속도가 느린 사용자에게는 효과가 더욱 악화됩니다.
아래에서는 서로를 기반으로 하는 세 가지 솔루션을 제시합니다.
async/await
(ES2017+, 트랜스파일러나 재생기를 사용하는 경우 이전 브라우저에서 작동)then() 的 Promise
사용(ES2015+, 많은 Promise 라이브러리 중 하나를 사용하는 경우 이전 브라우저에서 작동)이 세 가지 기능은 현재 브라우저와 Node 7+에서 사용할 수 있습니다.
ES2017+:
사용async/await 进行承诺
ECMAScript 2017 릴리스에는 비동기 함수에 대한 구문 수준 지원이 도입되었습니다.
async
和await
를 사용하면 "동기식"으로 비동기적으로 작성할 수 있습니다. 코드는 여전히 비동기식이지만 읽기/이해하기가 더 쉽습니다.
async 함수는 항상 Promise를 반환합니다.async/await
构建在 Promise 之上:async
函数始终返回 Promise。await
Promise 기반:await는 Promise를 "잠금 해제"하고 Promise가 해결하는 값을 생성하거나 Promise가 거부되면 오류를 발생시킵니다.
:async
函数或 JavaScript 模块。模块外部不支持顶级await
,因此您可能必须创建异步 IIFE (立即调用函数表达式)来启动异步
중요async 함수 또는 await만 사용할 수 있습니다. 가이드/모듈" rel="noreferrer">JavaScript 모듈
async. 최상위 await
는 모듈 외부에서 지원되지 않으므로 비동기 IIFE(즉시 호출되는 함수 표현식 )을 사용하여 async 컨텍스트를 시작합니다(모듈을 사용하지 않는 경우).및
findItem()
await에 대해 읽어보세요. 다음은 위의 delayed 함수
nodeasync/await
findItem()을 자세히 설명하는 예입니다. 으아악 현재 browser 및버전은
를 지원합니다. Babel
과 같은 이전 환경을 지원하기 위해regenerator
(또는 재생성을 사용하는 도구)를 사용하여 코드를 ES5로 변환할 수도 있습니다. 🎜 🎜 🎜함수가 콜백을 받아들이도록 하세요🎜🎜 🎜콜백은 함수 1이 함수 2로 전달되는 경우입니다. 함수 2는 준비되면 함수 1을 호출할 수 있습니다. 비동기 프로세스의 컨텍스트에서는 비동기 프로세스가 완료될 때마다 콜백이 호출됩니다. 일반적으로 결과는 콜백에 전달됩니다. 🎜질문의 예에서는
으아아아foo
接受回调并将其用作success
콜백을 만들 수 있습니다. 그래서 이건되었다
으아아아여기에서는 "인라인" 함수를 정의하지만 모든 함수 참조를 전달할 수 있습니다.
으아아아
으아아아foo
자체는 다음과 같이 정의됩니다.콜백
은 호출할 때callback
将引用我们调用时传递给foo
的函数,并将其传递给success
。 IE。一旦Ajax请求成功,$.ajax
将调用callback
并将响应传递给回调(可以用result
에 전달한 함수를 참조하여성공
에 전달합니다. 즉. Ajax 요청이 성공하면$.ajax
는callback
을 호출하고 응답을 콜백에 전달합니다(result
에서 참조할 수 있음). 이것이 우리가 콜백을 정의하는 방법입니다.)콜백에 전달하기 전에 응답을 처리할 수도 있습니다.
으아아아콜백을 사용하여 코드를 작성하는 것은 보기보다 쉽습니다. 결국 브라우저의 JavaScript는 주로 이벤트 중심(DOM 이벤트)입니다. Ajax 응답을 받는 것은 이벤트에 지나지 않습니다. 타사 코드를 사용해야 할 경우 어려움이 발생할 수 있지만 대부분의 문제는 애플리케이션 흐름만 생각하면 해결됩니다.
ES2015+: then()的 Promise >
을 사용하여Promise API는 새로운 ECMAScript 6(ES2015) 기능이지만 이미 우수한 브라우저 지원을 갖추고 있습니다. 표준 Promises API를 구현하고 비동기 함수의 사용 및 구성을 단순화하기 위한 추가 메서드를 제공하는 많은 라이브러리도 있습니다(예: Bluebird).
약속은 미래가치의 그릇입니다. Promise가 값을 수신하거나(resolved) 취소되면(rejected) 해당 값에 액세스하려는 모든 "리스너"에게 알립니다.
일반 콜백에 비해 장점은 코드를 분리할 수 있고 작성하기가 더 쉽다는 것입니다.
Promise 사용 예시: