동기 XMLHttpRequest를 사용하는 이유가 있습니까?
대부분의 모든 사람이 XMLHttpRequest를 사용하여 비동기 요청을 수행하는 것처럼 보이지만 동기 요청을 수행 할 수있는 기능이 있다는 사실은 그렇게해야하는 유효한 이유가 있음을 나타냅니다. 그렇다면 그 타당한 이유는 무엇일까요?
HTML 5 표준이 진행됨에 따라 더 인기가있을 것이라고 생각합니다. 웹 애플리케이션에 웹 워커에 대한 액세스 권한이 부여되면 Jonathan이 말했듯이 특정 요청이 다른 요청보다 먼저 발생하도록하기 위해 전용 웹 워커를 사용하는 개발자가 동기식 요청을 할 수 있습니다. 한 스레드의 현재 상황에서는 요청이 완료 될 때까지 차단되므로 이상적인 설계가 아닙니다.
동기식 XHR은 사용자 데이터를 저장하는 데 유용합니다. beforeunload
이벤트 를 처리하면 사용자가 페이지를 닫을 때 데이터를 서버에 업로드 할 수 있습니다.
비동기 옵션을 사용하여이 작업을 수행 한 경우 요청이 완료되기 전에 페이지가 닫힐 수 있습니다. 이를 동 기적으로 수행하면 요청이 예상대로 완료되거나 실패합니다.
최신 정보:
아래는 더 나은 비동기 요청 처리의 출현으로 요청이 완료 될 때까지 사용자가 어떤 작업을 수행하지 못하도록 의도적으로 차단하지 않는 한 동기 요청을 사용할 이유가 없다는 것을 암시했지만 전달에 실패했습니다. 악의적으로 들립니다. )
이것은 나쁘게 들릴 수 있지만 사용자가 페이지를 떠나기 전 또는 작업이 수행되기 전에 요청 (또는 일련의 요청)이 발생하는 것이 중요한 경우가 있습니다. 다른 코드 실행을 차단 (예 : 뒤로 버튼 방지) 할 수 있습니다. 잘못 설계된 시스템에 대한 오류 / 유지 보수를 줄일 수 있습니다 . 즉, 나는 그것을 야생 에서 본 적이 없으며 피해야한다는 것을 강조합니다.
promise 와 같은 라이브러리 는 콜백을 통해 프로세스를 연결하여 동시성을 가장합니다. 이는 브라우저가 사용자 (좋은 UX)에 대한 응답 성을 유지할 수 있도록 해주는 비 차단 이벤트를 주문하려는 대부분의 개발 요구에 적합합니다.
마찬가지로 모질라 문서에 명시된 가 동기식 요청을 사용해야 할 경우가 있습니다; 그러나 이러한 경우에 비콘 (IE / Safari에서는 사용할 수 없음) 을 사용하는 해결 방법도 나열되어 있습니다. 이것은 실험적이지만 표준 수용에 도달하면 동기 요청 관에 못을 박을 수 있습니다.
모든 종류의 트랜잭션과 같은 처리에서 또는 작업 순서가 필요한 모든 곳에서 동기 호출을 수행하고 싶을 것입니다.
예를 들어 노래를 재생 한 후 로그 아웃하도록 이벤트를 사용자 정의하고 싶다고 가정 해 보겠습니다. 로그 아웃 작업이 먼저 발생하면 노래가 재생되지 않습니다. 이를 위해서는 요청 동기화가 필요합니다.
또 다른 이유는 WebService로 작업 할 때, 특히 서버에서 수학을 수행 할 때입니다.
예 : 서버에 값이 1 인 변수가 있습니다.
Step (1) Perform Update: add 1 to variable Step (2) Perform Update: set variable to the power of 3 End Value: variable equals 8
단계 (2)가 먼저 발생하면 종료 값은 8이 아니라 2입니다. 따라서 작업 순서와 동기화가 필요합니다.
일반적인 실제 사례에서 동기 호출이 정당화되는 경우는 거의 없습니다. 로그인을 클릭 한 다음 사용자가 로그인해야하는 사이트 부분을 클릭하는 경우 일 수 있습니다.
다른 사람들이 말했듯이 브라우저를 묶을 수 있으므로 가능한 한 멀리 떨어져 있습니다.
하지만 동기 호출 대신에 사용자는 현재로드중인 이벤트를 중지 한 다음 다른 작업을 수행하기를 원합니다. 두 번째 이벤트가 시작되기 전에 첫 번째 이벤트가 종료되기 때문에 이것은 동기화입니다. 이렇게하려면 xml 연결 개체에서 abort () 메서드를 사용합니다.
요청이 허용되는 동안 사용자의 브라우저를 차단하는 것을 고려한다면 반드시 동기 요청을 사용하십시오.
요청 직렬화가 목표 인 경우 비동기 요청을 사용하여 이전 요청의 onComplete 콜백이 다음 줄에서 실행되도록 할 수 있습니다.
변수 위치의 리소스가 첫 번째 리소스에 의존하는 페이지의 다른 정적 리소스보다 먼저로드되어야 완벽하게 작동 할 때 사용되는 동기식 XHR 요청의 용도를 볼 수 있습니다. 사실, JavaScript 리소스는 특정 매개 변수 집합에 따라 서버의 가변 위치에 상주하는 반면 내 자신의 작은 하위 프로젝트에서 이러한 XHR 요청을 구현하고 있습니다. 후속 자바 스크립트 리소스는 이러한 가변 리소스에 의존하며 이러한 파일은 다른 의존 파일이로드되기 전에로드되도록 보장해야하므로 애플리케이션이 전체가됩니다.
그 아이디어 기반은 실제로 vol7ron의 답변으로 확장됩니다. 트랜잭션 기반 프로시 저는 실제로 동기 요청이 이루어져야하는 유일한 시간입니다. 대부분의 다른 경우에는 호출 후 DOM이 필요에 따라 업데이트되는 비동기 호출이 더 나은 대안입니다. 사용자 기반 시스템과 같은 대부분의 경우 특정 기능은 로그인 할 때까지 "승인되지 않은 사용자"에 대해 잠길 수 있습니다. 이러한 기능은 비동기 호출 후 DOM 업데이트 절차를 통해 잠금 해제됩니다.
마지막으로이 문제에 대한 대부분의 개인의 요점에 동의한다고 말해야합니다. 가능하면 동기식 XHR 요청은 작동 방식에 따라 브라우저가 동기식 호출로 잠기므로 피해야합니다. 동기 요청을 구현할 때는 브라우저가 일반적으로 잠기는 방식으로 수행해야합니다. 예를 들어 페이지로드가 실제로 발생하기 전에 HEAD 섹션에서 말입니다.
UI 차단이 정확히 원하는 동작 인 실제 사례가 많이 있습니다.
여러 필드가있는 앱을 가져오고 일부 필드는이 필드의 값과 기타 필드 값을 입력으로 제공하는 원격 서버에 대한 xmlhttp 호출로 유효성을 검사해야합니다.
동기 모드에서는 로직이 단순하고 사용자가 경험하는 블로킹이 매우 짧고 문제가 없습니다.
비동기 모드에서 사용자는 초기 필드의 유효성을 검사하는 동안 다른 필드의 값을 변경할 수 있습니다. 이러한 변경 사항은 아직 유효성이 검사되지 않은 초기 필드의 값으로 다른 xmlhttp 호출을 트리거합니다. 초기 유효성 검사가 실패하면 어떻게됩니까? 순수한 엉망. 동기화 모드가 더 이상 사용되지 않고 금지되면 응용 프로그램 논리가 처리하기 어려워집니다. 기본적으로 잠금을 관리하려면 응용 프로그램을 다시 작성해야합니다 (예 : 유효성 검사 프로세스 동안 다른 항목 비활성화). 코드 복잡성이 엄청나게 증가합니다. 그렇게하지 않으면 논리 오류가 발생하고 궁극적으로 데이터가 손상 될 수 있습니다.
기본적으로 질문은 차단되지 않은 UI 경험이나 데이터 손상 위험이 더 중요한 것은 무엇입니까? 대답은 W3C가 아니라 응용 프로그램 개발자에게 달려 있습니다.
jQuery uses synchronous AJAX internally under some circumstances. When inserting HTML that contains scripts, the browser will not execute them. The scripts need to be executed manually. These scripts may attach click handlers. Assume a user clicks on an element before the handler is attached and the page would not function as intended. Therefore to prevent race conditions, synchronous AJAX would be used to fetch those scripts. Because synchronous AJAX effectively blocks everything else, it can be sure that scripts and events execute in the right order.
As of 2015 desktop javascript apps are becoming more popular. Usually in those apps when loading local files (and loading them using XHR is a perfectly valid option), the load speed is so fast that there is little point overcomplicating the code with async. Of course there might be cases where async is the way to go (requesting content from the internet, loading really big files or a huge number of files in a single batch), but otherwise sync works just fine (and is much easier to use).
What happens if you make a synchronous call in production code?
The sky falls down.
No seriously, the user does not like a locked up browser.
I use it to validate a username, during the check that the username does not exist already.
I know it would be better to do that asynchronously, but then I should use a different code for this particular validation rule. I explain better. My validation setup uses some validation functions, which return true or false, depending if the data is valid.
Since the function has to return, I cannot use asynchronous techniques, so I just make that synchronous and hope that the server will answer promptly enough not to be too noticeable. If I used an AJAX callback, then I would have to handle the rest of the execution differently from the other validation methods.
Sometimes you have an action that depends in others. For example, action B can only be started if A is finished. The synchronous approach is usually used to avoid race conditions. Sometimes using a synchronous call is a simpler implementation then creating complex logic to check every state of your asynchronous calls that depend on each other.
The problem with this approach is that you "block" the user's browser until the action is finished (until the request returns, finishes, loads, etc). So be careful when using it.
I use synchronous calls when developing code- whatever you did while the request was commuting to and from the server can obscure the cause of an error.
When it's working, I make it asynchronous, but I try to include an abort timer and failure callbacks, cause you never know...
Reason:
Let's say you have an ajax application which needs to do half a dozen http gets to load various data from the server before the user can do any interaction.
Obviously you want this triggered from onload.
Synchronous calls work very well for this without any added complexity to the code. It is simple and straightforward.
Drawback:
The only drawback is that your browser locks up until all data is loaded or a timeout happens. As for the ajax application in question, this isn't much of a problem because the application is of no use until all the initial data is loaded anyway.
Alternative?
However many browsers lock up all windows/tabs when while the javascript is busy in any one of them, which is a stupid browser design problem - but as a result blocking on possibly slow network gets is not polite if it keeps users from using other tabs while waiting for ajax page to load.
However, it looks like synchronous gets have been removed or restricted from recent browsers anyway. I'm not sure if that's because somebody decided they were just always bad, or if browser writers were confused by the WC Working Draft on the topic.
http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method does make it look like (see section 4.7.3) you are not allowed to set a timeout when using blocking mode. Seems counter intuitive to me: Whenever one does blocking IO it's polite to set a reasonable timeout, so why allow blocking io but not with a user specified timeout?
My opinion is that blocking IO has a vital role in some situations but must be implemented correctly. While it is not acceptable for one browser tab or window to lock up all other tabs or windows, that's a browser design flaw. Shame where shame is due. But it is perfectly acceptable in some cases for an individual tab or window to be non-responsive for a couple of seconds (i.e. using blocking IO/HTTP GET) in some situations -- for example, on page load, perhaps a lot of data needs to be before anything can be done anyway. Sometimes properly implemented blocking code is the cleanest way to do it.
Of course equivalent function in this case can be obtained using asynchronous http gets, but what sort of goofy routine is required?
I guess I would try something along these lines:
On document load, do the following: 1: Set up 6 global "Done" flag variables, initialized to 0. 2: Execute all 6 background gets (Assuming the order didn't matter)
Then, the completion callbacks for each of the 6 http get's would set their respective "Done" flags. Also, each callback would check all the other done flags to see if all 6 HTTP gets had completed. The last callback to complete, upon seeing that all others had completed, would then call the REAL init function which would then set everything up, now that the data was all fetched.
If the order of the fetching mattered -- or if the webserver was unable to accept multiple requests at same time -- then you would need something like this:
In onload(), the first http get would be launched. In it's callback, the second one would be launched. In it's callback, the third -- and so on and so forth, with each callback launching the next HTTP GET. When the last one returned, then it would call the real init() routine.
SYNC vs ASYNC: What is the difference?
Basically it boils down to this:
console.info('Hello, World!');
doSomething(function handleResult(result) {
console.info('Got result!');
});
console.info('Goodbye cruel world!');
When doSomething
is synchronous this would print:
Hello, World!
Got result!
Goodbye cruel world!
In contrast, if doSomething
is asynchronous, this would print:
Hello, World!
Goodbye cruel world!
Got result!
Because the function doSomething
is doing it's work asynchronously, it returns before it's work is done. So we only get the result after printing Goodbye cruel world!
If we are depending on the result of an asynch call, we need to place the depending code in the callback:
console.info('Hello, World!');
doSomething(function handleResult(result) {
console.info('Got result!');
if (result === 'good') {
console.info('I feel great!');
}
else {
console.info('Goodbye cruel world!');
}
});
As such, just the fact that 2 or three things need to happen in order is no reason to do them synchronously (though sync code is easier for most people to work with).
WHY USE SYNCHRONOUS XMLHTTPREQUEST?
There are some situations where you need the result before the called function completes. Consider this scenario:
function lives(name) {
return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');
Suppose we have no control over the calling code (the console.info
line) and need to change function lives
to ask the server... There is no way we can do an async request to the server from within lives
and still have our response before lives
completes. So we wouldn't know whether to return true
or false
. The only way to get the result before the function completes is by doing a synchronous request.
As Sami Samhuri
mentions in his answer, a very real scenario where you may need an answer to your server request before your function terminates is the onbeforeunload
event, as it's the last function from your app that will ever run before the window being closed.
I DON'T NEED SYNCH CALLS, BUT I USE THEM ANYWAY AS THEY ARE EASIER
Please don't. Synchronous calls lock up your browser and make the app feel unresponsive. But you are right. Async code is harder. There is, however a way to make dealing with it much easier. Not as easy as sync code, but it's getting close: Promises.
Here is an example: Two asynch calls should both complete succesfully before a third segment of code may run:
var carRented = rentCar().then(function(car){
gasStation.refuel(car);
});
var hotelBooked = bookHotel().then(function(reservation) {
reservation.confirm();
});
Promise.all([carRented, hotelBooked]).then(function(){
// At this point our car is rented and our hotel booked.
goOnHoliday();
});
Here is how you would implement bookHotel
:
function bookHotel() {
return new Promise(function(resolve, reject){
if (roomsAvailable()) {
var reservation = reserveRoom();
resolve(reservation);
}
else {
reject(new Error('Could not book a reservation. No rooms available.'));
}
});
}
See also: Write Better JavaScript with Promises.
XMLHttpRequest
is traditionally used for asynchronous requests. Sometimes (for debugging, or specific business logic) you would like to change all/several of the async calls in one page to sync.
You would like to do it without changing everything in your JS code. The async/sync flag gives you that ability, and if designed correctly, you need only change one line in your code/change the value of one var
during execution time.
Firefox (and probable all non-IE browsers) does not support async XHR timeOut.
HTML5 WebWorkers do support timeouts. So, you may want to wrap sync XHR request to WebWorker with timeout to implement async-like XHR with timeout behaviour.
I just had a situation where asynchronous requests for a list of urls called in succession using forEach (and a for loop) would cause the remaining requests to be cancelled. I switched to synchronous and they work as intended.
Well here's one good reason. I wanted to do an http request then, depending on the result, call click() on an input type=file. This is not possible with asynchronous xhr or fetch. The callback loses the context "user action", so the call click() is ignored. Synchronous xhr saved my bacon.
onclick(event){
//here I can, but I don't want to.
//document.getElementById("myFileInput").click();
fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
.then((response)=>response.json())
.then(function (validResult) {
if (validResult.success) {
//here, I can't.
document.getElementById("myFileInput").click();
}
});
}
참고URL : https://stackoverflow.com/questions/2088318/is-there-any-reason-to-use-a-synchronous-xmlhttprequest
'program tip' 카테고리의 다른 글
위임 생성자를 사용하는 동안 멤버 초기화 (0) | 2020.09.17 |
---|---|
어떤 이벤트가 (0) | 2020.09.17 |
Angular2의 프로덕션 모드와 개발 모드의 차이점은 무엇입니까? (0) | 2020.09.17 |
json.js와 json2.js의 차이점 (0) | 2020.09.17 |
Ruby에서 문자열을 주어진 길이의 덩어리로 자르는 가장 좋은 방법은 무엇입니까? (0) | 2020.09.16 |