복붙노트

[JQUERY] 어떻게 비동기 호출의 응답을 반환합니까?

JQUERY

어떻게 비동기 호출의 응답을 반환합니까?

해결법


  1. 1.아약스의 A는 비동기를 의미합니다. 수단 요청을 송신 (또는 오히려 응답을 수신하는) 일반적인 실행 흐름 취출된다. 당신의 예에서, $ 아약스 즉시 반환하고 다음 문, 반환 결과는 ;, 성공 콜백도 불렀다대로 전달 기능을하기 전에 실행됩니다.

    아약스의 A는 비동기를 의미합니다. 수단 요청을 송신 (또는 오히려 응답을 수신하는) 일반적인 실행 흐름 취출된다. 당신의 예에서, $ 아약스 즉시 반환하고 다음 문, 반환 결과는 ;, 성공 콜백도 불렀다대로 전달 기능을하기 전에 실행됩니다.

    여기서 희망 동기 및 비동기 흐름 명확한 차이를 만든다 비유이다 :

    당신은 친구에게 전화를 걸 상상하고 당신을 위해 무언가를 찾아달라고. 시간이 걸릴 수 있지만, 당신은 전화를 기다리고 친구가 당신에게 당신이 필요로하는 답을 제공 할 때까지, 공간으로 응시.

    당신이 "정상"코드를 포함하는 함수 호출을 할 때 동일하게 일어나고있다 :

    function findItem() {
        var item;
        while(item_not_found) {
            // search
        }
        return item;
    }
    
    var item = findItem();
    
    // Do something with item
    doSomethingElse();
    

    있는 FindItem 실행하는 데 시간이 오래 걸릴 수 있지만, 모든 코드는 VAR 항목 =있는 FindItem () 이후에 오는; 함수가 결과를 반환 할 때까지 기다려야합니다.

    당신은 같은 이유로 다시 친구에게 전화. 그러나 이번에는 당신이 서둘러 그에게 말해 그는 휴대 전화에 다시 전화해야합니다. 당신은 전화를 끊고 집에두고 당신이 계획대로 할. 친구가 당신을 호출하면, 당신은 그가 당신에게 준 정보를 다루고있다.

    즉, Ajax 요청을 수행 할 때 무슨 일이 일어나고 있는지 정확히.

    findItem(function(item) {
        // Do something with the item
    });
    doSomethingElse();
    

    대신 응답을 기다리는 중, 실행은 즉시 계속 Ajax 호출 후 문이 실행됩니다. 결국 응답을 얻으려면, 당신은 응답이 수신되면 호출되는 함수, 콜백 제공 (통지 뭔가? 전화 다시?). 콜백이 호출 전에 호출 후에 오는 모든 문이 실행됩니다.

    자바 스크립트의 비동기 특성을 안아! 특정 비동기 작업 (그래서에서 'Ajax'수행)하는 동기를 제공하지만, 일반적으로 특히 브라우저 맥락에서 그들을 사용하는 실망입니다.

    왜 나쁜 물어합니까입니까?

    자바 스크립트는 응답하고, 브라우저와 UI를 잠급니다 어떤 장기 실행 프로세스의 UI 스레드에서 실행됩니다. 또한, 실행을 계속할지 여부를 사용자에게 자바 스크립트와 브라우저의 실행 시간에 상한이있다.

    이 모든 것은 정말 나쁜 사용자 경험이다. 사용자는 모든 것이 잘 작동할지 여부를 알 수 없습니다. 또한, 효과는 느린 연결을 가진 사용자를 위해 더 악화 될 것입니다.

    다음에 우리는 서로의 상단에있는 모든 건물에 세 가지 다른 솔루션 볼 것이다 :

    세 명 모두 현재 브라우저에서 사용할 수 있으며, 노드 7+.

    2017 년 출시 된 ECMA 스크립트 버전은 비동기 기능에 대한 구문 수준의 지원을 소개했다. 비동기 및 await를의 도움으로, 당신은 "동기 스타일"에서 비동기 쓸 수 있습니다. 코드는 여전히 비동기이지만, 이해 / 읽기 쉽다.

    비동기 / await를이 약속의 상단에 빌드 : 비동기 함수는 항상 약속을 반환합니다. await를 "펼쳤다"약속으로 해결되거나 약속이 거부 된 경우 오류가 발생 된 약속과 가치 중 결과.

    중요 : 당신은 비동기 함수 내에서 await를 사용할 수 있습니다. 당신이 비동기 컨텍스트를 시작하는 비동기 인생 (즉시 호출 기능 식)하게해야 할 수도 있습니다, 그래서 지금, 최상위 await를 아직 지원되지 않습니다.

    당신은 비동기에 대한 자세한 읽고 MDN에 기다리고 있습니다.

    여기서 상기 지연 위에 빌드 예이다 :

    // Using 'superagent' which will return a promise.
    var superagent = require('superagent')
    
    // This is isn't declared as `async` because it already returns a promise
    function delay() {
      // `delay` returns a promise
      return new Promise(function(resolve, reject) {
        // Only `delay` is able to resolve or reject the promise
        setTimeout(function() {
          resolve(42); // After 3 seconds, resolve the promise with value 42
        }, 3000);
      });
    }
    
    
    async function getAllBooks() {
      try {
        // GET a list of book IDs of the current user
        var bookIDs = await superagent.get('/user/books');
        // wait for 3 seconds (just for the sake of this example)
        await delay();
        // GET information about each book
        return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
      } catch(error) {
        // If any of the awaited promises was rejected, this catch block
        // would catch the rejection reason
        return null;
      }
    }
    
    // Start an IIFE to use `await` at the top level
    (async function(){
      let books = await getAllBooks();
      console.log(books);
    })();
    

    현재 브라우저와 노드 버전은 비동기 / await를 지원합니다. 또한 나이가 재생기의 도움으로 ES5에 코드를 변환하여 환경 (또는 도구 등의 바벨로 사용 재생기, 그)를 지원할 수 있습니다.

    콜백은 단순히 다른 함수에 전달하는 기능입니다. 이 준비가 될 때마다 다른 기능은 전달 된 함수를 호출 할 수 있습니다. 비동기 처리가 완료 될 때마다 비동기 프로세스의 맥락에서 콜백이 호출됩니다. 일반적으로, 결과는 콜백에 전달됩니다.

    질문의 예에서, 당신은 콜백을 받아 성공 콜백으로 사용할 푸 할 수 있습니다. 그래서 이거

    var result = foo();
    // Code that depends on 'result'
    

    가된다

    foo(function(result) {
        // Code that depends on 'result'
    });
    

    여기에서 우리는 함수를 "인라인"를 정의하지만, 당신은 어떤 함수 참조를 전달할 수 있습니다 :

    function myCallback(result) {
        // Code that depends on 'result'
    }
    
    foo(myCallback);
    

    다음과 같이 자체가 정의된다 foo는 :

    function foo(callback) {
        $.ajax({
            // ...
            success: callback
        });
    }
    

    콜백은 우리가 그것을 호출하고 우리는 단순히 성공에 그것을 통과 할 때 우리가 foo는에 전달하는 기능을 참조합니다. 즉 Ajax 요청이 성공하면, $ 아약스는 콜백을 호출합니다 (이 우리가 콜백을 정의하는 방법이기 때문에, 결과라고 할 수있다) 콜백에 대한 응답을 전달합니다.

    또한 콜백에 전달하기 전에 응답을 처리 할 수 ​​있습니다 :

    function foo(callback) {
        $.ajax({
            // ...
            success: function(response) {
                // For example, filter the response
                callback(filtered_response);
            }
        });
    }
    

    그것은 보일 수보다 콜백을 사용하여 코드를 작성하는 것이 더 쉽습니다. 결국, 브라우저에서 자바 스크립트를 무겁게 이벤트 중심 (DOM 이벤트)입니다. Ajax 응답을받는 것은 아무 것도 있지만 이벤트입니다. 타사 코드와 함께 일해야 할 때 어려움이 발생할 수 있지만, 대부분의 문제는 응용 프로그램의 흐름을 통해 단지 생각에 의해 해결 될 수 있습니다.

    약속 API는 ECMAScript를 6 (ES2015)의 새로운 기능이지만 이미 좋은 브라우저 지원을하고 있습니다. 표준 약속 API를 구현하고 비동기 기능의 사용 및 구성을 용이하게하기 위해 추가 방법 (예를 들어, 블루 버드)를 제공하는 많은 도서관이있다.

    약속은 미래 값에 대한 컨테이너입니다. ,이 값에 액세스 할 그 "청취자"모든 통지 약속이 값을 수신하면 (그것은 해결) 또는 해제시 (거부).

    일반 콜백 이상의 장점은 당신이 당신의 코드를 분리 할 수 ​​있도록 그들이 구성하기 쉽다는 것이다.

    여기에 약속을 사용하는 간단한 예입니다 :

    function delay() {
      // `delay` returns a promise
      return new Promise(function(resolve, reject) {
        // Only `delay` is able to resolve or reject the promise
        setTimeout(function() {
          resolve(42); // After 3 seconds, resolve the promise with value 42
        }, 3000);
      });
    }
    
    delay()
      .then(function(v) { // `delay` returns a promise
        console.log(v); // Log the value once it is resolved
      })
      .catch(function(v) {
        // Or do something else if it is rejected 
        // (it would not happen in this example, since `reject` is not called).
      });
    

    우리의 아약스에 적용하는 것은 우리가이 같은 약속을 사용할 수 있습니다 전화 :

    function ajax(url) {
      return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.onload = function() {
          resolve(this.responseText);
        };
        xhr.onerror = reject;
        xhr.open('GET', url);
        xhr.send();
      });
    }
    
    ajax("/echo/json")
      .then(function(result) {
        // Code depending on result
      })
      .catch(function() {
        // An error occurred
      });
    

    서비스를 약속 모든 장점을 설명하는 것은이 답변의 범위를 벗어나지 만 새로운 코드를 작성하는 경우, 당신은 그들을 심각하게 고려해야합니다. 그들은 코드의 큰 추상화와 분리를 제공합니다.

    약속에 대한 자세한 정보 : HTML5 바위 - 자바 스크립트 약속

    이연 객체 (약속 API가 표준화되기 전에) 약속의 jQuery의 사용자 정의 구현입니다. 그들은 거의 약속처럼 행동하지만 약간 다른 API를 노출합니다.

    jQuery를의 모든 아약스 방법은 이미 당신이 당신 함수에서 반환 할 수 있습니다 (실제로는 연기 객체의 약속)는 "연기 대상"을 반환합니다 :

    function ajax() {
        return $.ajax(...);
    }
    
    ajax().done(function(result) {
        // Code depending on result
    }).fail(function() {
        // An error occurred
    });
    

    약속과 연기 객체가 미래 값에 대한 단지 컨테이너 있음을 유의하십시오, 그들은 값 자체되지 않습니다. 예를 들어, 다음을 있다고 가정 :

    function checkPassword() {
        return $.ajax({
            url: '/password',
            data: {
                username: $('#username').val(),
                password: $('#password').val()
            },
            type: 'POST',
            dataType: 'json'
        });
    }
    
    if (checkPassword()) {
        // Tell the user they're logged in
    }
    

    이 코드는 위의 비동기 문제를 잘못 이해. 이 서버의 '/ 암호'페이지를 확인하면서 특히, $ 아약스 ()는 코드를 동결하지 않습니다 - 그것은 서버에 요청을 전송하고 대기하는 동안, 그것은 즉시 jQuery를 아약스 이연 객체가 아닌 응답을 반환 서버에서. 은 if 문은 항상 가고 있음을 의미합니다,이 이연 객체를 얻을 사실로 취급하고 사용자가 로그인 한 것처럼 진행합니다. 좋은하지 않습니다.

    하지만 수정은 간단합니다 :

    checkPassword()
    .done(function(r) {
        if (r) {
            // Tell the user they're logged in
        } else {
            // Tell the user their password was bad
        }
    })
    .fail(function(x) {
        // Tell the user something bad happened
    });
    

    내가 언급 한 바와 같이, 일부 (!) 비동기 작업을하는 동기가있다. 나는 그들의 사용을 옹호하지만, 완전성 '을 위해, 여기 당신이 동기 호출을 수행 할 어떻게하지 않습니다

    당신이 직접 XMLHttpRequest의 개체를 사용하는 경우, 세 번째 인수가 .open하기로 false를 전달.

    당신이 jQuery를 사용하는 경우에는 false로 비동기 옵션을 설정할 수 있습니다. 이 옵션은 jQuery를 1.8부터 사용되지 않습니다. 그런 다음 중 하나 여전히 성공 콜백 또는 액세스 jqXHR 객체의 responseText 속성을 사용할 수 있습니다 :

    function foo() {
        var jqXHR = $.ajax({
            //...
            async: false
        });
        return jqXHR.responseText;
    }
    

    당신이 다른 jQuery를 아약스 방법을 사용하는 경우 등 $ 갔지, $ .getJSON으로, 당신은 (당신은 단지 $ 아약스로 구성 매개 변수를 전달할 수 있기 때문에) 아약스 $로 변경해야합니다.

    헤드 업! 동기 JSONP 요청을 할 수 없습니다. 본질적으로 JSONP는 항상 비동기 (또 하나의 이유도이 옵션을 고려하지합니다).


  2. 2.코드는 다음의 라인을 따라 뭔가해야한다 :

    코드는 다음의 라인을 따라 뭔가해야한다 :

    function foo() {
        var httpRequest = new XMLHttpRequest();
        httpRequest.open('GET', "/echo/json");
        httpRequest.send();
        return httpRequest.responseText;
    }
    
    var result = foo(); // always ends up being 'undefined'
    

    펠릭스 클링은 AJAX를 위해 jQuery를 사용하는 사람들에 대한 답을 작성하는 좋은 일을, 내가하지 않은 사람들을위한 대안을 제공하기로 결정했습니다했다.

    (참고, 새로운 가져 오기 API를 사용하는 사람들을 위해, 각도 또는 약속 나는 아래에 다른 대답을 추가했습니다)

    당신이 이것을 읽고 확실하지 않은 경우는, 다른 대답에서 "문제의 설명"의 짧은 요약, 그것을 읽었다.

    AJAX의 A는 비동기를 의미합니다. 수단 요청을 송신 (또는 오히려 응답을 수신하는) 일반적인 실행 흐름 취출된다. 당신의 예에서, .send 즉시 반환하고 다음 문, 반환 결과는 ;, 성공 콜백도 불렀다대로 전달 기능을하기 전에 실행됩니다.

    당신이 반환 할 때이 방법은 사용자가 정의한 리스너는 정의되지 않은 반환하고 값을 의미하는, 아직 실행하지 않았다.

    다음은 간단한 비유입니다

    function getFive(){ 
        var a;
        setTimeout(function(){
             a=5;
        },10);
        return a;
    }
    

    (깡깡이)

    는 A = 5 부분이 아직 실행되지 않았기 때문에 반환 값은 정의되지 않는다. AJAX는 서버가 그 값이 무엇인지 브라우저를 말할 수있는 기회를 얻기 전에 당신은 값을 반환하고, 다음과 같은 역할을합니다.

    이 문제에 대한 한 가지 가능한 솔루션은 코드입니다 다시 적극적으로 계산이 완료 할 때 무엇을해야 하는지를 프로그램을 말하고.

    function onComplete(a){ // When the code completes, do this
        alert(a);
    }
    
    function getFive(whenDone){ 
        var a;
        setTimeout(function(){
             a=5;
             whenDone(a);
        },10);
    }
    

    이는 CPS라고합니다. 기본적으로, 우리가 getFive에게이 완료 될 때 수행 할 작업을 전달하는, 우리가 어떻게 할 때 반응하는 우리의 코드를 말하는 것 (우리의 AJAX 호출, 또는이 경우에는 시간 제한 같은) 이벤트 완료.

    사용법은 다음과 같습니다

    getFive(onComplete);
    

    어떤 화면에 "5"를 경고한다. (깡깡이).

    이 문제를 해결하는 방법 두 가지 방법이 기본적으로 있습니다 :

    동기 AJAX에 관해서는, 그것을하지 않습니다! 펠릭스의 대답은 나쁜 생각하는 이유에 대해 몇 가지 설득력있는 주장을 제기한다. 이를 요약하면, 서버가 응답을 반환 할 때까지 사용자의 브라우저를 동결하고 아주 나쁜 사용자 경험을 만듭니다. 그 이유에 MDN에서 가져온 또 다른 간략한 요약이다 :

    당신이 그것을 할 수있는 경우에, 당신은 플래그를 전달할 수있는 방법은 다음과 같습니다이다 :

    var request = new XMLHttpRequest();
    request.open('GET', 'yourURL', false);  // `false` makes the request synchronous
    request.send(null);
     
    if (request.status === 200) {// That's HTTP for 'ok'
      console.log(request.responseText);
    }
    

    함수가 콜백을 받아 보자. 예에서 코드 foo는 콜백을 적용 할 수있다. 우리는 어떻게 foo는이 완료 될 때 반응하는 우리의 코드를 이야기 할 수 있습니다.

    그래서:

    var result = foo();
    // code that depends on `result` goes here
    

    된다 :

    foo(function(result) {
        // code that depends on `result`
    });
    

    여기에서 우리는 익명 함수를 통과,하지만 우리는 그냥 쉽게 모양을 만들고, 기존 기능에 대한 참조를 전달할 수 :

    function myHandler(result) {
        // code that depends on `result`
    }
    foo(myHandler);
    

    콜백 디자인의 정렬이 수행하는 방법에 대한 자세한 내용은 펠릭스의 답변을 확인합니다.

    자,하자 자체가 그에 따라 행동하는 foo는 정의

    function foo(callback) {
        var httpRequest = new XMLHttpRequest();
        httpRequest.onload = function(){ // when the request is loaded
           callback(httpRequest.responseText);// we're calling our method
        };
        httpRequest.open('GET', "/echo/json");
        httpRequest.send();
    }
    

    (깡깡이)

    우리는 지금 (만들 핸들러와 같은 실패) 우리 foo는 기능은 AJAX이 성공적으로 완료 될 때 실행하는 작업을 수락 응답 상태가 적절하지 (200)와 동작한다면 우리가 확인하여이 더욱 확장 할 수 있습니다 만들었습니다. 효과적으로 우리의 문제를 해결.

    당신은 여전히 ​​힘든 시간을 이해하는 데 문제가있는 경우이 MDN에서 시작 가이드를 얻는 AJAX를 참조하십시오.


  3. 3.2 (우선 벤자민 Gruenbaum & 펠릭스 클링에서 답변을 읽기) XMLHttpRequest의

    2 (우선 벤자민 Gruenbaum & 펠릭스 클링에서 답변을 읽기) XMLHttpRequest의

    당신은 jQuery를 사용하고 현대적인 브라우저에서 또한 내가이 방법을 사용하는 것이 좋습니다 모바일 브라우저에서 작동하는 좋은 짧은 XMLHttpRequest의 2를 원하지 않는 경우 :

    function ajax(a, b, c){ // URL, callback, just a placeholder
      c = new XMLHttpRequest;
      c.open('GET', a);
      c.onload = b;
      c.send()
    }
    

    당신이 볼 수 있듯이 :

    이 Ajax 호출의 응답을 (세 XMLHttpRequest의 VAR 이름을 사용)하는 데는 두 가지 방법이 있습니다 :

    가장 간단한 :

    this.response
    

    아니면 바인딩 어떤 이유로 () 클래스에 콜백을위한 경우 :

    e.target.response
    

    예:

    function callback(e){
      console.log(this.response);
    }
    ajax('URL', callback);
    

    또는 (위의 사람은 더 나은 익명 함수는 항상 문제가있는 것입니다) :

    ajax('URL', function(e){console.log(this.response)});
    

    쉽게 아무것도.

    이제 어떤 사람들은 아마을 onreadystatechange 또는 심지어 XMLHttpRequest의 변수 이름을 사용하는 것이 좋습니다 말할 것입니다. 그건 틀렸어요.

    XMLHttpRequest의 고급 기능을 확인

    그것은 모든 * 최신 브라우저를 지원했다. 그리고 XMLHttpRequest의 2가 존재하기 때문에 나는이 방법을 사용하고 있습니다로 확인할 수 있습니다. 내가 사용하는 모든 브라우저에서 문제의 모든 유형이 없었어요.

    당신이 국가 2 헤더를 얻으려면을 onreadystatechange에만 유용합니다.

    당신이 내부 콜백을 실행하기 위해 필요로 XMLHttpRequest의 변수 이름을 사용하여 또 다른 큰 오류 인 온로드 / oreadystatechange 폐쇄 다른 당신이 그것을 잃었다.

    이제 당신이 뭔가 더 복잡한 사용 후 및 FormData를 원하는 경우 쉽게이 기능을 확장 할 수 있습니다 :

    function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
      c = new XMLHttpRequest;
      c.open(e||'get', a);
      c.onload = b;
      c.send(d||null)
    }
    

    다시 ... 그것은 매우 간단한 기능이지만, 그것을 얻을 및 포스트 않습니다.

    사용의 예 :

    x(url, callback); // By default it's get so no need to set
    x(url, callback, 'post', {'key': 'val'}); // No need to set post data
    

    OR (document.getElementsByTagName ( '형태') [0])으로 전체 폼 요소를 건네

    var fd = new FormData(form);
    x(url, callback, 'post', fd);
    

    또는 일부 사용자 지정 값을 설정 :

    var fd = new FormData();
    fd.append('key', 'val')
    x(url, callback, 'post', fd);
    

    당신은 내가 동기화를 구현하지 않은 볼 수 있듯이 ... 그것은 나쁜 일입니다.

    왜 쉬운 방법하지 않는 것이 ... 가졌어요?

    주석에 오류 &&의 사용을 언급 한 바와 같이 동기는 완전히 대답의 요점을 깰 않습니다. 적절한 방법으로 Ajax를 사용하는 좋은 간단한 방법은 무엇입니까?

    오류 거래

    function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
      c = new XMLHttpRequest;
      c.open(e||'get', a);
      c.onload = b;
      c.onerror = error;
      c.send(d||null)
    }
    
    function error(e){
      console.log('--Error--', this.type);
      console.log('this: ', this);
      console.log('Event: ', e)
    }
    function displayAjax(e){
      console.log(e, this);
    }
    x('WRONGURL', displayAjax);
    

    위의 스크립트에서, 당신은 기능을 손상하지 않도록 정적으로 정의 된 오류 처리기가 있습니다. 오류 핸들러는 너무 다른 기능을 사용할 수 있습니다.

    하지만 실제로는 오류를 얻을 수있는 유일한 방법은 모든 브라우저에서 오류가 발생하는 경우 잘못된 URL을 작성하는 것입니다.

    사용자 설정 사용자 지정 헤더, 방울 배열 버퍼 또는 무엇이든에 responseType을 설정하면 오류 처리기는 어쩌면 유용합니다 ...

    당신이 방법으로 'POSTAPAPAP'을 통과하더라도 그것은 오류가 발생하지 않습니다.

    심지어는 오류가 발생하지 않습니다 formdata 당신이 'fdggdgilfdghfldj'를 전달하는 경우.

    허용되지 않는 방법으로 첫 번째 경우에는 오류가 this.statusText 아래 displayAjax () 안에있다.

    두 번째 경우, 단순히 작동합니다. 당신은 당신이 오른쪽 골대 데이터를 전달하는 경우 서버 측에서 확인해야합니다.

    허용되지 도메인 간 자동으로 오류가 발생합니다.

    오류 응답에서 오류 코드가 없습니다.

    오류로 설정된 경우에만 this.type이있다.

    당신이 완전히 오류가 통제 할 수없는 경우에 왜 오류 처리기를 추가? 오류의 대부분은 콜백 함수 displayAjax이 내부에 반환됩니다 ().

    그래서 : 오류 검사에 대한 필요를 복사하고 제대로 URL을 붙여 넣기 할 수있어하지 않는 경우. ;)

    PS : 첫 번째 테스트로 나는 ( 'X', displayAjax) × 썼다 ... 그리고 그것은 완전히 응답을 가지고 ... ??? 그래서 HTML이있는 폴더를 선택하고 'x.xml'라는 파일이 있었다. 당신이 당신의 파일의 확장자를 잊지 그래서 경우에도 XMLHttpRequest의 2는 IT를 찾을 수 있습니다. I LOL'd

    파일 동기화 읽기

    그렇게하지 마십시오.

    당신은 부하 동안 좋은 큰 .txt 인 파일 동기의 브라우저를 차단합니다.

    function omg(a, c){ // URL
      c = new XMLHttpRequest;
      c.open('GET', a, true);
      c.send();
      return c; // Or c.response
    }
    

    지금 당신은 할 수있다

     var res = omg('thisIsGonnaBlockThePage.txt');
    

    비 비동기 방식으로이 작업을 수행하는 다른 방법은 없습니다. (그래, 심각의 setTimeout 루프 ...하지만에?)

    당신은 당신이 항상 각 요청에 대해 다른 기능을 사용하는 어떤 API를하거나 자신의 목록의 파일이나 작업하는 경우 또 다른 점은 ...입니다 ...

    당신은 항상 당신이 하나의 기능을 필요 같은 XML / JSON 또는 어떤로드 페이지가있는 경우에만. 이 경우, 약간에게 아약스 기능을 수정하고 특별한 기능 B를 교체합니다.

    기능은 위의 기본적인 사용을위한 것입니다.

    당신은 기능을 확장 할 경우 ...

    그래 넌 할수있어.

    난 단지 GET과 더불어, API가 많이 나는 모든 HTML 페이지에 통합하는 최초의 기능 중 하나이 답변의 첫 번째 아약스 기능은 사용하고 ...

    하지만 당신은 XMLHttpRequest를 2 물건을 많이 할 수 있습니다 :

    나는 캔버스, 훨씬 더 채우기 웹 SQL의 base64images와 데이터베이스 및 사용 (이력서, 파일 리더, 파일 시스템과 양쪽에 범위를 사용) 다운로드 관리자, 다양한 이미지 resizers 컨버터를했다 ...하지만 이러한 경우는 해당하는 기능을 작성해야 목적은 ... 때때로 당신은, 당신은 헤더, 재정의 마임을 설정할 수 있습니다 BLOB, 배열 버퍼를 필요로하고 많은 더있다 ...

    그러나 여기서 문제는 ... 아약스 응답을 반환하는 방법이다 (나는 쉬운 방법을 추가했습니다.)


  4. 4.이 수단의 AngularJS와는 jQuery를가 (연기에), 네이티브 XHR의 교체 (가져 오기), EmberJS, BackboneJS의 저장 또는 반환 약속이 모든 노드 라이브러리.

    이 수단의 AngularJS와는 jQuery를가 (연기에), 네이티브 XHR의 교체 (가져 오기), EmberJS, BackboneJS의 저장 또는 반환 약속이 모든 노드 라이브러리.

    코드는 다음의 라인을 따라 뭔가해야한다 :

    function foo() {
        var data;
        // or $.get(...).then, or request(...).then, or query(...).then
        fetch("/echo/json").then(function(response){
            data = response.json();
        });
        return data;
    }
    
    var result = foo(); // result is always undefined no matter what.
    

    펠릭스 클링은 AJAX에 대한 콜백 jQuery를 사용하는 사람들에 대한 답을 작성하는 훌륭한 일을했다. 나는 네이티브 XHR에 대한 답을 가지고있다. 이 답변은 프론트 엔드 또는 백엔드에 하나의 약속의 일반적인 사용을위한 것입니다.

    브라우저 및 NodeJS / io.js로 서버에 자바 스크립트 동시성 모델은 비동기 및 반응이다.

    그 때는 핸들러가 아닌 그 아래의 코드 후 - 당신은 약속이, 그 후에 핸들러는 항상 비동기 적으로 실행 반환하는 메소드를 호출 할 때마다.

    데이터를 반환 할 때이 수단이는 아직 실행되지 않은 정의한 핸들러입니다. 이 차례로 수단에 당신이 반환하고 값이 시간에 올바른 값으로 설정되지 않았 음.

    여기에 문제에 대한 간단한 비유입니다 : getFive 함수 () { VAR 데이터; 에서는 setTimeout은 (함수 () {// 앞으로 1 초에 대한 타이머를 설정 데이터 = 5; // 두 번째 한 후,이 작업을 수행 } 1000); 데이터를 반환; } document.body.innerHTML getFive = (); //`undefined` 여기되지 5

    데이터 = 5 부분이 아직 실행되지 않았기 때문에 데이터의 값은 정의되지 않는다. 그것은 아마도 두 번째로 실행되지만 그 시간에 그 반환 값에 무관하다.

    작업이 아직 (AJAX, 서버 호출, IO, 타이머)를 발생하지 않았기 때문에 요청이 그 값이 무엇인지 코드를 말할 수있는 기회를 얻기 전에 당신은 값을 반환하고 있습니다.

    이 문제에 대한 한 가지 가능한 솔루션은 코드입니다 다시 적극적으로 계산이 완료 할 때 무엇을해야 하는지를 프로그램을 말하고. 약속 적극적 자연 (시간에 민감한) 시간적 됨으로써이를 가능하게한다.

    약속은 시간이 지남에 따라 값입니다. 약속, 그들은 어떤 값을 대기로 상태를 시작하고에 정착 할 수 있습니다 :

    그 후에는 항상 영원히 같은 상태로 유지됩니다 일단 약속은 상태를 변경할 수 있습니다. 당신은 자신의 가치와 핸들 오류를 추출하기 위해 약속을 한 후 핸들러를 첨부 할 수 있습니다. 다음 핸들러는 호출의 체인 수 있습니다. 약속은 그들을 돌려 API를 사용하여 만들어집니다. 예를 들어, 현대 AJAX 교체 가져 오거나 jQuery의 $ 갔지 반환 약속.

    우리는 그것에서 약속하고 반환 뭔가 그 때는 호출 할 때 - 우리는 처리 값에 대한 약속을 얻는다. 우리는 또 다른 약속을 반환하는 경우 우리는 놀라운 일을 얻을 것이다,하지만하자 우리의 말을 누르고 있습니다.

    의 우리가 약속 위의 문제를 해결할 수있는 방법을 살펴 보자. 첫째,하자가 위에서 지연 기능을 만들기위한 약속 생성자를 사용하여 약속 상태에 대한 우리의 이해를 보여줍니다

    function delay(ms){ // takes amount of milliseconds
        // returns a new promise
        return new Promise(function(resolve, reject){
            setTimeout(function(){ // when the time is up
                resolve(); // change the promise to the fulfilled state
            }, ms);
        });
    }
    

    우리가 사용 약속의 setTimeout을 변환 한 후 이제, 우리는 그것을 계산하기 위해 다음 사용할 수 있습니다 :

    함수 지연 (밀리 초) {// 밀리 량을 얻어 // 새로운 약속을 반환 반환 새로운 약속 (기능 (해결, 거부) { 에서는 setTimeout은 (함수 () {시간까지입니다 // 때 결의(); // 충족 된 상태로 약속을 변경 } MS); }); } getFive 함수 () { 우리가 약속을 RETURNING하고 // 약속은 우리의 가치에 대한 래퍼입니다 기억 반환 지연 (100) 그 때는 (함수 () {//이 약속은 준비가되면 5를 반환; // 값 5를 반환 약속 반환 값에 대해 모두 }) } // 우리가 전화 사이트에이처럼 포장 _have_, 우리는 일반 값을 액세스 할 수 없습니다 getFive (). 다음 (기능 (오) { document.body.innerHTML = 오; });

    기본적으로, 우리가 때문에 동시성 모델을 할 수없는 값을 반환하는 대신에 - 우리는 다음과 포장을 푸는 수있는 값의 래퍼를 반환하고 있습니다. 그것은 당신이 그 다음으로 열 수있는 상자 같은거야.

    이것은 당신이 할 수있는, 원래의 API 호출에 대한 같은 약자

    function foo() {
        // RETURN the promise
        return fetch("/echo/json").then(function(response){
            return response.json(); // process it inside the `then`
        });
    }
    
    foo().then(function(response){
        // access the value inside the `then`
    })
    

    그래서 이것은 단지뿐만 아니라 작동합니다. 우리는 우리가 이미 비동기 호출에서 값을 반환 할 수 있지만, 우리가 약속을 사용하고 처리를 수행하도록 체인 수 배웠다. 우리는 지금 비동기 호출의 응답을 반환하는 방법을 알고있다.

    ES6는 중간에 반환하고 그들이에 있었던 점을 다시 시작할 수있는 기능입니다 발전기를 소개합니다. 이것은 예를 들어, 시퀀스 일반적으로 유용합니다 :

    function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
        yield 1;
        yield 2;
        while(true) yield 3;
    }
    

    반복 된이 될 수 순서 1,2,3,3,3,3, ...의 반복자를 반환하는 함수입니다. 이것은 그 자체로 재미와 가능성의 많은 공간을 개방하는 동안 하나의 특정 흥미로운 경우가 있습니다.

    우리가 생산하고있는 순서가 아니라 숫자보다는 행동의 순서 인 경우 - 액션이 산출 될 때마다 우리는 기능을 일시 정지 할 수 있습니다 우리가 기능을 다시 시작하기 전에 기다립니다. 약속 :입니다 - 그래서 그 대신 숫자의 순서, 우리는 미래의 값의 순서가 필요합니다.

    이 다소 까다로운하지만 매우 강력한 트릭은 우리가 동기 방식으로 비동기 코드를 작성할 수 있습니다. 당신을 위해 이렇게 여러 가지 "주자"하나를 작성하는 코드의 짧은 몇 줄하지만이 답변의 범위를 벗어있다. 여기 블루 버드의 Promise.coroutine를 사용 하겠지만, 공동 또는 Q.async 같은 다른 래퍼가있다.

    var foo = coroutine(function*(){
        var data = yield fetch("/echo/json"); // notice the yield
        // code here only executes _after_ the request is done
        return data.json(); // data is defined
    });
    

    이 방법은 우리가 다른 코 루틴에서 소비 할 수있는 약속 자체를 반환합니다. 예를 들면 :

    var main = coroutine(function*(){
       var bar = yield foo(); // wait our earlier coroutine, it returns a promise
       // server call done here, code below executes when done
       var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
       console.log(baz); // runs after both requests done
    });
    main();
    

    ES7에서 더 표준화이 몇 가지 제안은 지금하지만 그들 모두 당신이 할 수있는 await를 약속이 있습니다. 이 비동기 및 await를 키워드를 추가하여 위의 ES6 제안에 대한 그냥 "설탕"(더 좋은 구문)입니다. 위의 예를 만들기 :

    async function foo(){
        var data = await fetch("/echo/json"); // notice the await
        // code here only executes _after_ the request is done
        return data.json(); // data is defined
    }
    

    아직 약속을 그냥 같은 :)를 반환


  5. 5.당신은 잘못 Ajax를 사용하고 있습니다. 아이디어는 아무것도 반환해야하지만 대신에 데이터를 처리하는 콜백 함수라는 뭔가에 데이터를 넘겨하지 않는 것입니다.

    당신은 잘못 Ajax를 사용하고 있습니다. 아이디어는 아무것도 반환해야하지만 대신에 데이터를 처리하는 콜백 함수라는 뭔가에 데이터를 넘겨하지 않는 것입니다.

    그건:

    function handleData( responseData ) {
    
        // Do what you want with the data
        console.log(responseData);
    }
    
    $.ajax({
        url: "hi.php",
        ...
        success: function ( data, status, XHR ) {
            handleData(data);
        }
    });
    

    아무것도하지 않습니다 제출 핸들러에서 아무것도 반환. 대신 데이터 오프 양손, 또는 당신이 성공 함수 내에서 직접으로 원하는 일을해야합니다.


  6. 6.가장 간단한 솔루션은 자바 스크립트 함수를 작성하고 아약스 성공 콜백 호출입니다.

    가장 간단한 솔루션은 자바 스크립트 함수를 작성하고 아약스 성공 콜백 호출입니다.

    function callServerAsync(){
        $.ajax({
            url: '...',
            success: function(response) {
    
                successCallback(response);
            }
        });
    }
    
    function successCallback(responseObj){
        // Do something like read the response and show data
        alert(JSON.stringify(responseObj)); // Only applicable to JSON response
    }
    
    function foo(callback) {
    
        $.ajax({
            url: '...',
            success: function(response) {
               return callback(null, response);
            }
        });
    }
    
    var result = foo(function(err, result){
              if (!err)
               console.log(result);    
    }); 
    

  7. 7.나는 끔찍한 - 찾고, 손으로 그린 ​​만화로 응답 할 것이다. 두 번째 이미지는 결과 코드 예제에서 정의되지 이유입니다.

    나는 끔찍한 - 찾고, 손으로 그린 ​​만화로 응답 할 것이다. 두 번째 이미지는 결과 코드 예제에서 정의되지 이유입니다.


  8. 8.AngularJS와를 사용하는 사람들을 위해, 약속을 사용하여이 상황을 처리 할 수 ​​있습니다.

    AngularJS와를 사용하는 사람들을 위해, 약속을 사용하여이 상황을 처리 할 수 ​​있습니다.

    , 그것이 말하는 이곳까지

    또한 여기에 좋은 설명을 찾을 수 있습니다.

    실시 예는 아래에 언급 된 문서에서 발견.

      promiseB = promiseA.then(
        function onSuccess(result) {
          return result + 1;
        }
        ,function onError(err) {
          //Handle error
        }
      );
    
     // promiseB will be resolved immediately after promiseA is resolved 
     // and its value will be the result of promiseA incremented by 1.
    

    다음 예에서 모습 Angular2하지만, 그것은 Angular2와 Observable 인을 사용하는 것이 좋습니다.

     search(term: string) {
         return this.http
      .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
      .map((response) => response.json())
      .toPromise();
    

    }

    당신은이 방법으로 그것을 소비 할 수

    search() {
        this.searchService.search(this.searchField.value)
          .then((result) => {
        this.result = result.artists.items;
      })
      .catch((error) => console.error(error));
    }
    

    여기에 원래의 게시물을 참조하십시오. 그러나 타이프 라이터는 당신이 그것을 사용하려는 경우, 당신은 그것을 위해 플러그인해야 할 수도 있습니다, 기본 ES6의 약속을 지원하지 않습니다.

    또한 여기에 여기에 정의 사양 약속입니다.


  9. 9.여기에 대한 답변의 대부분은 단일 비동기 작업이있을 때 유용 제안을하지만 배열이나 기타리스트 같은 구조의 각 항목에 대해 비동기 작업을 할 필요가있을 때 때때로,이납니다. 유혹이 작업을 수행하는 것입니다 :

    여기에 대한 답변의 대부분은 단일 비동기 작업이있을 때 유용 제안을하지만 배열이나 기타리스트 같은 구조의 각 항목에 대해 비동기 작업을 할 필요가있을 때 때때로,이납니다. 유혹이 작업을 수행하는 것입니다 :

    // WRONG
    var results = [];
    theArray.forEach(function(entry) {
        doSomethingAsync(entry, function(result) {
            results.push(result);
        });
    });
    console.log(results); // E.g., using them, returning them, etc.
    

    예:

    // 잘못된 VAR theArray = [1, 2, 3]; VAR 결과 = []; theArray.forEach (함수 (엔트리) { doSomethingAsync (항목 기능 (결과) { (결과) results.push; }); }); ( "결과", 결과) CONSOLE.LOG; // 예를 들어, 등을 돌려, 그들을 사용 함수 doSomethingAsync (값 콜백) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 콜백 (값 * 2); } Math.floor (인 Math.random () * 200)); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    일을하지 않는 이유는 doSomethingAsync에서 콜백 당신이 결과를 사용하려는 시간에 아직 실행하지 않은 것입니다.

    당신은 (어떤 종류의 또는 목록) 배열을 가지고 있고 각 항목에 대한 작업을 비동기 수행하려는 경우 따라서, 당신은 두 가지 옵션이 있습니다 : 병렬 (중복) 또는 직렬 (순서대로 차례 차례)에서 작업을 수행합니다.

    당신은 많은 콜백을 늘어 놓던 때 당신은 그들 모두를 시작하고 기대하고 얼마나 많은 콜백을 추적하고 결과를 사용할 수 있습니다 :

    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                console.log("Results:", results); // E.g., using the results
            }
        });
    });
    

    예:

    VAR theArray = [1, 2, 3]; VAR 결과 = []; VAR 기대 = theArray.length; theArray.forEach (함수 (엔트리 인덱스) { doSomethingAsync (항목 기능 (결과) { 결과 [지수 = 결과; 경우 (--expecting === 0) { // 완료! ( "결과", 결과) CONSOLE.LOG; // 예를 들어, 결과를 사용하여 } }); }); 함수 doSomethingAsync (값 콜백) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 콜백 (값 * 2); } Math.floor (인 Math.random () * 200)); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    (우리는 ... 기대 페지 그냥 results.length === theArray.length 사용하지만, 그 잎을 우리는 호출이 뛰어난 반면 theArray이 변경 될 가능성을 열 수 있습니다)

    우리는 결과 순서가 도착하더라도, 그것은에 관한 항목과 같은 위치에 결과에 결과를 저장하는 데 대해 forEach에서 인덱스를 사용하는 방법 공지 사항 (가 시작 된 순서대로 비동기 호출 할 필요는 완료되지 이후 ).

    하지만 당신은 함수에서 그 결과를 반환하기 위해 무엇을해야하는 경우? 다른 답변이 지적한 것처럼, 당신은 할 수 없습니다; 당신은 당신의 기능을 수락하고 콜백을 호출 (또는 약속을 반환) 있어야합니다. 다음은 콜백 버전입니다 :

    function doSomethingWith(theArray, callback) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    callback(results);
                }
            });
        });
    }
    doSomethingWith(theArray, function(results) {
        console.log("Results:", results);
    });
    

    예:

    함수 doSomethingWith (theArray 콜백) { VAR 결과 = []; VAR 기대 = theArray.length; theArray.forEach (함수 (엔트리 인덱스) { doSomethingAsync (항목 기능 (결과) { 결과 [지수 = 결과; 경우 (--expecting === 0) { // 완료! (결과) 콜백; } }); }); } doSomethingWith ([1, 2, 3, 기능 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값 콜백) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 콜백 (값 * 2); } Math.floor (인 Math.random () * 200)); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    또는 여기에 대신 약속을 반환 버전입니다 :

    function doSomethingWith(theArray) {
        return new Promise(function(resolve) {
            var results = [];
            var expecting = theArray.length;
            theArray.forEach(function(entry, index) {
                doSomethingAsync(entry, function(result) {
                    results[index] = result;
                    if (--expecting === 0) {
                        // Done!
                        resolve(results);
                    }
                });
            });
        });
    }
    doSomethingWith(theArray).then(function(results) {
        console.log("Results:", results);
    });
    

    doSomethingAsync 우리에게 오류를 통과하는 경우 물론, 우리가 사용하는 우리가 오류를 받았을 때 약속을 거부하는 거부 할 것입니다.)

    예:

    함수 doSomethingWith (theArray) { 반환 새로운 약속 (기능 (해결) { VAR 결과 = []; VAR 기대 = theArray.length; theArray.forEach (함수 (엔트리 인덱스) { doSomethingAsync (항목 기능 (결과) { 결과 [지수 = 결과; 경우 (--expecting === 0) { // 완료! 해결 (결과); } }); }); }); } doSomethingWith ([1, 2, 3]). 다음 (함수 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값 콜백) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 콜백 (값 * 2); } Math.floor (인 Math.random () * 200)); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    (또는 ... 또는, 당신은 doSomethingAsync에 대해 그 반환 약속을 래퍼를 만들 수있는 다음 아래 수행)

    doSomethingAsync 당신에게 약속을 제공하는 경우 Promise.all을 사용할 수 있습니다 :

    function doSomethingWith(theArray) {
        return Promise.all(theArray.map(function(entry) {
            return doSomethingAsync(entry);
        }));
    }
    doSomethingWith(theArray).then(function(results) {
        console.log("Results:", results);
    });
    

    당신이 doSomethingAsync 두 번째와 세 번째 인수를 무시 것을 알고 있다면, 당신은 단지 (지도 세 개의 인수로 콜백을 호출하지만 대부분의 사람들은 처음으로 대부분의 시간의 사용)가 직접 매핑을 전달할 수 있습니다 :

    function doSomethingWith(theArray) {
        return Promise.all(theArray.map(doSomethingAsync));
    }
    doSomethingWith(theArray).then(function(results) {
        console.log("Results:", results);
    });
    

    예:

    함수 doSomethingWith (theArray) { 반환 Promise.all (theArray.map (doSomethingAsync)); } doSomethingWith ([1, 2, 3]). 다음 (함수 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 반환 새로운 약속 (기능 (해결) { 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 의지 (값 * 2); } Math.floor (인 Math.random () * 200)); }); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    Promise.all들이 모두 해결 될 때 당신이 그것을주는 약속의 모든 결과의 배열과의 약속을 해결하거나 제공 약속의 첫 번째가 거부 할 때 약속을 거부합니다.

    당신은 작업을 병렬로 싶지 않아 가정 해? 당신이 그들에게 또 다른 후 하나를 실행하려는 경우, 당신은 당신이 다음을 시작하기 전에 완료 할 각 작업을 기다릴 필요가있다. 여기에을 수행하고 결과에 콜백을 호출하는 함수의 예입니다 :

    function doSomethingWith(theArray, callback) {
        var results = [];
        doOne(0);
        function doOne(index) {
            if (index < theArray.length) {
                doSomethingAsync(theArray[index], function(result) {
                    results.push(result);
                    doOne(index + 1);
                });
            } else {
                // Done!
                callback(results);
            }
        }
    }
    doSomethingWith(theArray, function(results) {
        console.log("Results:", results);
    });
    

    우리는 일련의 일을하고 있기 때문에 우리는 우리가 순서가 결과를 얻을 수 없습니다 알고 있기 때문에 (우리가) results.push (결과를 사용할 수 있습니다. 우리가 사용했을 수 위의 결과에서 [인덱스] = 결과 ;,하지만, 다음 예 중 일부에서 우리가 사용하는 인덱스가 없습니다.)

    예:

    함수 doSomethingWith (theArray 콜백) { VAR 결과 = []; doOne (0); doOne 기능 (인덱스) { 경우 (인덱스

    (또는 ... 다시, 당신에게 약속을 제공 doSomethingAsync에 대한 래퍼를 구축하고 아래의 작업을 수행)

    doSomethingAsync 당신에게 약속을 제공하는 경우, 당신은 (아마도 바벨과 같은 transpiler와) ES2017 + 구문을 사용할 수 있습니다, 당신은에 대한-과 await를 함께 비동기 기능을 사용할 수 있습니다 :

    async function doSomethingWith(theArray) {
        const results = [];
        for (const entry of theArray) {
            results.push(await doSomethingAsync(entry));
        }
        return results;
    }
    doSomethingWith(theArray).then(results => {
        console.log("Results:", results);
    });
    

    예:

    비동기 함수 doSomethingWith (theArray) { CONST 결과 = []; (theArray의 CONST 항목) {에 대한 results.push (await를 doSomethingAsync (항목)); } 결과를 반환; } doSomethingWith ([1, 2, 3]). 다음 (함수 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 반환 새로운 약속 (기능 (해결) { 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 의지 (값 * 2); } Math.floor (인 Math.random () * 200)); }); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    당신이 패턴을 "감소 약속"ES2017은 + 구문 (아직), 당신은에 변화를 사용할 수 있습니다 사용할 수없는 경우 (이것은 보통의 약속은 우리가 다음에 하나에서 결과를 전달하지 않는 때문에 줄이고, 대신에보다 더 복잡하다 어레이에서의 결과)를 수집 :

    function doSomethingWith(theArray) {
        return theArray.reduce(function(p, entry) {
            return p.then(function(results) {
                return doSomethingAsync(entry).then(function(result) {
                    results.push(result);
                    return results;
                });
            });
        }, Promise.resolve([]));
    }
    doSomethingWith(theArray).then(function(results) {
        console.log("Results:", results);
    });
    

    예:

    함수 doSomethingWith (theArray) { 창 theArray.reduce (함수 (p 엔트리) { {) p.then (함수 (결과를 반환 그 때는 창 doSomethingAsync (엔트리 () 함수 (결과) { (결과) results.push; 결과를 반환; }); }); } Promise.resolve ([])); } doSomethingWith ([1, 2, 3]). 다음 (함수 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 반환 새로운 약속 (기능 (해결) { 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 의지 (값 * 2); } Math.floor (인 Math.random () * 200)); }); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }

    ... ES2015 + 화살표 함수 덜 복잡 :

    function doSomethingWith(theArray) {
        return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
            results.push(result);
            return results;
        })), Promise.resolve([]));
    }
    doSomethingWith(theArray).then(results => {
        console.log("Results:", results);
    });
    

    예:

    함수 doSomethingWith (theArray) { 창 theArray.reduce ((p, 입력) => p.then (결과 => doSomethingAsync (엔트리) 그 때는 (결과 => { (결과) results.push; 결과를 반환; })) Promise.resolve ([])); } doSomethingWith ([1, 2, 3]). 다음 (함수 (결과) { ( "결과", 결과) CONSOLE.LOG; }); 함수 doSomethingAsync (값) { CONSOLE.LOG은 (+ 값 "의 비동기 동작 시작"); 반환 새로운 약속 (기능 (해결) { 에서는 setTimeout (함수 () { CONSOLE.LOG은 (+ 값 "의 비동기 동작 완료"); 의지 (값 * 2); } Math.floor (인 Math.random () * 200)); }); } 이 .as - 콘솔 래퍼 { 최대 높이 : 100 % 중요한;! }


  10. 10.이 예에서보세요 :

    이 예에서보세요 :

    var app = angular.module('plunker', []);
    
    app.controller('MainCtrl', function($scope,$http) {
    
        var getJoke = function(){
            return $http.get('http://api.icndb.com/jokes/random').then(function(res){
                return res.data.value;  
            });
        }
    
        getJoke().then(function(res) {
            console.log(res.joke);
        });
    });
    

    당신이 getJoke가 해결 약속을 반환 볼 수 있듯이 (res.data.value를 반환 할 때이 해결됩니다). 당신이 $ http.get을 요청 때까지 기다려야 그래서 완료된 다음을 console.log (res.joke)는 (보통 비동기 흐름으로) 실행됩니다.

    이것은 plnkr입니다 :

    http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/

    ES6 방법 (비동기 - await를)

    (function(){
      async function getJoke(){
        let response = await fetch('http://api.icndb.com/jokes/random');
        let data = await response.json();
        return data.value;
      }
    
      getJoke().then((joke) => {
        console.log(joke);
      });
    })();
    

  11. 11.이것은 당신을 위해 잘 작동 할 것이다 많은 새로운 자바 스크립트 프레임 워크에서 사용되는 두 가지 방법으로 데이터 바인딩 장소 또는 저장 개념 중 하나입니다 ...

    이것은 당신을 위해 잘 작동 할 것이다 많은 새로운 자바 스크립트 프레임 워크에서 사용되는 두 가지 방법으로 데이터 바인딩 장소 또는 저장 개념 중 하나입니다 ...

    당신이 각도를 사용하는 경우에 따라서, 반응하거나 할 다른 프레임 워크는 두 가지 방법으로 데이터는 결과를 가지고 있으므로이 문제는 간단하게 정의되지 않은 = 당신의 결과는 첫 번째 단계에서 정의되지, 너무 쉽게 단어, 당신을 위해 고정되어 저장 개념을 결합 또는 당신이 바로 당신이 결과를 얻을로 다음 데이터를 받기 전에,이 업데이트되고있는 귀하의 Ajax 호출의 응답을 새로운 값으로 할당받을 ...

    이 질문에 질문하지만 당신은 예를 들어, 순수 자바 스크립트 또는 jQuery를에 그것을 할 수 있습니까?

    당신은 우리가 다음 성공 () 또는 같은 일부 기능이 약속 예를 들어, 최근에 당신을 위해 그것을 처리 할 관찰, 콜백을 사용 약속 할 수 있습니다 () 실행되는 데이터는 콜백 또는 함수를 구독과 함께, 당신을 위해 준비가 같은 경우 관찰합니다.

    당신이 jQuery를 사용하는 귀하의 경우 예를 들어, 당신은 이런 식으로 뭔가를 할 수 있습니다 :

    $(document).ready(function(){
        function foo() {
            $.ajax({url: "api/data", success: function(data){
                fooDone(data); //after we have data, we pass it to fooDone
            }});
        };
    
        function fooDone(data) {
            console.log(data); //fooDone has the data and console.log it
        };
    
        foo(); //call happens here
    });
    

    약속이 비동기 거즈를 할 수있는 새로운 방법입니다 관찰 가능한에 대한 자세한 내용은 연구하십시오.


  12. 12.그것은 자바 스크립트의 '신비'로 어려움을 겪고있는 동안 우리가 직면 한 매우 일반적인 문제입니다. 나 오늘이 비밀을 신비성을 해보자.

    그것은 자바 스크립트의 '신비'로 어려움을 겪고있는 동안 우리가 직면 한 매우 일반적인 문제입니다. 나 오늘이 비밀을 신비성을 해보자.

    의 간단한 자바 스크립트 함수 시작하자 :

    function foo(){
    // do something 
     return 'wohoo';
    }
    
    let bar = foo(); // bar is 'wohoo' here
    

    즉 (코드의 각 라인은 순서대로 다음 일 전 '의 작업 완료'이다) 간단한 동기 함수 호출을, 그리고 예상대로 결과는 동일합니다.

    이제 코드의 모든 라인이 순차적으로 '완료'되지 않도록하는 것이 우리의 기능에 약간의 지연을 도입하여, 트위스트의 비트를 추가 할 수 있습니다. 따라서, 함수의 비동기 동작을 에뮬레이션합니다 :

    function foo(){
     setTimeout( ()=>{
       return 'wohoo';
      }, 1000 )
    }
    
    let bar = foo() // bar is undefined here
    

    그래서 당신이 갈이, 그 지연은 우리가 기대하는 기능은 부러! 하지만 정확히 무슨 일이 있었? 당신이 코드를 보면 음, 사실은 매우 논리적입니다. 함수 푸 (), 실행시에, 복귀 아무것도 (즉 리턴 값은 정의되지 않는다)하지만 '여행 애호가'를 반환 초 후에 기능을 실행하는 타이머를 시작하지 않는다. 당신이 볼 수 그러나, 줄에 할당 된 값은 즉 단지 정의되지 않은 아무것도 foo는에서 즉시 반환 물건은 ()이다.

    그래서, 우리는 어떻게이 문제를 해결합니까?

    의이 약속에 대한 우리의 기능을 물어 보자. 약속은 무엇을 의미하는지에 대해 정말 : 이것은 함수가 미래에 얻을 수있는 출력을 제공하도록 보장하는 것을 의미한다. 그래서 위의 우리의 작은 문제에 대한 행동을 보자 :

    function foo(){
       return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
        setTimeout ( function(){ 
          // promise is RESOLVED , when execution reaches this line of code
           resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
        }, 1000 )
      })
    }
    
    let bar ; 
    foo().then( res => {
     bar = res;
     console.log(bar) // will print 'wohoo'
    });
    

    따라서, 요약 한 것입니다 - 등 AJAX 기반의 호출과 같은 비동기 기능을 해결하기 위해, 당신이 (당신이 반환하려는) 값을 해결하기 위해 약속을 사용할 수 있습니다. 따라서, 한마디로 당신은 비동기 기능에 대신 반환하는 값을 해결.

    외에도 다음 사용 / 캐치 작업에 약속에서, 또 하나 개의 방법이 존재한다. 아이디어는 코드의 다음 행으로 이동하기 전에, 비동기 기능을 인식하고 해결하기 위해 약속을 기다릴 것입니다. 그것은하지만 다른 구문 접근, 여전히 후드 바로 약속입니다. 상황이 명확하게하려면 아래 비교를 찾을 수 있습니다 :

    function saveUsers(){
         getUsers()
          .then(users => {
             saveSomewhere(users);
          })
          .catch(err => {
              console.error(err);
           })
     }
    
      async function saveUsers(){
         try{
            let users = await getUsers()
            saveSomewhere(users);
         }
         catch(err){
            console.error(err);
         }
      }
    

  13. 13.또 다른 방법은 비동기 함수의 값을 반환하는 비동기 함수의 결과를 저장할 목적으로 전달하는 것이다.

    또 다른 방법은 비동기 함수의 값을 반환하는 비동기 함수의 결과를 저장할 목적으로 전달하는 것이다.

    여기서 동일한 예이다 :

    var async = require("async");
    
    // This wires up result back to the caller
    var result = {};
    var asyncTasks = [];
    asyncTasks.push(function(_callback){
        // some asynchronous operation
        $.ajax({
            url: '...',
            success: function(response) {
                result.response = response;
                _callback();
            }
        });
    });
    
    async.parallel(asyncTasks, function(){
        // result is available after performing asynchronous operation
        console.log(result)
        console.log('Done');
    });
    

    나는 비동기 작업 중에 값을 저장하기 위해 결과 객체를 사용하고 있습니다. 이 결과도 비동기 작업 후 사용할 수 있습니다.

    나는이 방법을 많이 사용합니다. 나는 연속 모듈을 통해 결과 다시가 관련된 배선 곳이 방법이 어떻게 작동하는지 잘 알고 관심이있을 것입니다.


  14. 14.약속과 콜백이 많은 상황에서 잘 작동하지만, 같은 것을 표현하기 뒤쪽에 통증이있다 :

    약속과 콜백이 많은 상황에서 잘 작동하지만, 같은 것을 표현하기 뒤쪽에 통증이있다 :

    if (!name) {
      name = async1();
    }
    async2(name);
    

    당신은 async1를 통과 끝장; 이름이 정의되어 있는지 확인 여부와 그에 따라 콜백을 호출합니다.

    async1(name, callback) {
      if (name)
        callback(name)
      else {
        doSomething(callback)
      }
    }
    
    async1(name, async2)
    

    이 작은 예에 괜찮 동안 관련 유사 사례와 오류 처리를 많이 가지고 때 짜증나 가져옵니다.

    섬유는 문제를 해결하는 데 도움이됩니다.

    var Fiber = require('fibers')
    
    function async1(container) {
      var current = Fiber.current
      var result
      doSomething(function(name) {
        result = name
        fiber.run()
      })
      Fiber.yield()
      return result
    }
    
    Fiber(function() {
      var name
      if (!name) {
        name = async1()
      }
      async2(name)
      // Make any number of async calls from here
    }
    

    현재 프로젝트를 체크 아웃 할 수 있습니다.


  15. 15.다음의 예 나는 쇼를 작성하는 방법에있다

    다음의 예 나는 쇼를 작성하는 방법에있다

    이 작업 예는 독립적이다. 그것은 통화를 할 수 윈도우 XMLHttpRequest 객체를 사용하는 간단한 요청 객체를 정의합니다. 그것은 완료 될 약속의 무리를 기다리는 간단한 함수를 정의합니다.

    문맥. 이 예는 쿼리 문자열의 주어진 집합에 대한 재생 목록 개체를 검색하기 위해 스포티 파이 웹 API 엔드 포인트를 조회한다 :

    [
     "search?type=playlist&q=%22doom%20metal%22",
     "search?type=playlist&q=Adele"
    ]
    

    결과를 분석, ExecutionBlock를 스포티 파이 사용자 개체의 목록입니다 결과 배열에 따라 약속의 새로운 세트를 예약하고 비동기 ExecutionProfileBlock 내에서 새로운 HTTP 호출을 실행 - 각 항목에 대해 새로운 약속 블록을 발사합니다.

    그런 다음 당신에게 산란 여러 완전히 비동기 중첩 된 HTTP 호출을 할 수있는 중첩 된 약속 구조를보고, Promise.all을 통해 전화의 각 부분 집합에서 결과를 가입 할 수 있습니다.

    노트 최근 스포티 파이 검색 API는 요청 헤더에 지정하는 액세스 토큰이 필요합니다 :

    -H "Authorization: Bearer {your access token}" 
    

    그래서, 당신은 당신이 요청 헤더에 토큰에 대한 액세스를 둘 필요가 다음 예제를 실행합니다 :

    VAR spotifyAccessToken = "YourSpotifyAccessToken"; VAR 콘솔 = { 기록 : 함수 (S)를 { document.getElementById를 ( "콘솔"). innerHTML을 + = S + "
    " } } // 간단한 XMLHttpRequest의 // https://davidwalsh.name/xmlhttprequest에 따라 SimpleRequest = { 호출 기능 (무엇을, 응답) { VAR 요청; (window.XMLHttpRequest) 경우 {// 모질라, 사파리, ... 요청은 새로운 인 XMLHttpRequest () =; } 다른 경우 (window.ActiveXObject) {// 인터넷 익스플로러 {시도 요청은 새로운 ActiveXObject ( 'MSXML2.XMLHTTP를') =; } 캐치 (예) { {시도 요청은 새로운 ActiveXObject ( '에서는 Microsoft.XMLHTTP를') =; } 캐치 (전자) {} } } // 상태 변경 request.onreadystatechange = 함수 () { (request.readyState === 4) {//하는 경우에 (request.status === (200)) {// 전체 경우 응답 (request.responseText) } 그밖에 응답(); } } request.open ( 'GET'무엇을, TRUE); request.setRequestHeader ( "권한", "베어러"+ spotifyAccessToken); (NULL) request.send; } } // PromiseAll VAR promiseAll = 함수 (항목, 블록이 완료 실패) { var에 자신이 =; VAR 약속 = [], 인덱스 = 0; items.forEach (함수 (항목) { promises.push (함수 (항목, ⅰ) { 반환 새로운 약속 (기능 (해결, 거부) { 만약 (블럭) { block.apply (이, [아이템 인덱스 해결 거부]); } }); } (항목, ++ 인덱스)) }); Promise.all (약속) 그 때는 (기능 AcceptHandler (결과) { (완료) 완료 (결과)의 경우; } 함수의 ErrorHandler (에러) { 경우 (에러) (실패) 실패; }); }; // promiseAll // LP : 지연 수행 블록 VAR ExecutionBlock 기능을 = (항목, 인덱스, 해결, 거부) { var에 URL = "https://api.spotify.com/v1/" URL + = 항목; CONSOLE.LOG (URL) SimpleRequest.call (URL, 기능 (결과) { 경우 (결과) { VAR profileUrls = JSON.parse (결과) .playlists.items.map (함수 (항목, 인덱스) { item.owner.href를 반환; }) 해결 (profileUrls); } 다른 { (새 오류 ( "호출 오류")) 거부; } }) } 도착 = "검색은? TYPE = 재생 및 Q = % 22doom 20metal % 22 %" "검색? 유형 = 재생 목록 및 Q = 아델" ] promiseAll (편곡, 기능 (항목, 인덱스, 해결, 거부) { CONSOLE.LOG는 ( "요청 만들기 ["+ 인덱스 + "]") ExecutionBlock (항목, 인덱스, 해결, 거부); } 함수 (결과) {// 집계 결과 CONSOLE.LOG (+ results.length "모든 정보가 수신"); //console.log(JSON.stringify(results[0, NULL, 2)); ///// promiseall 다시 VAR ExecutionProfileBlock 기능을 = (항목, 인덱스, 해결, 거부) { SimpleRequest.call (항목 기능 (결과) { 경우 (결과) { VAR OBJ = JSON.parse (결과); 결의({ 이름 : obj.display_name를, 추종자 : obj.followers.total, URL : obj.href }); } // 결과 }) } // ExecutionProfileBlock promiseAll (결과 [0], 함수 (항목, 인덱스 해결 거부) { 요청 //console.log("Making [ "+ 인덱스 +"] "항목 +) ExecutionProfileBlock (항목, 인덱스, 해결, 거부); } 함수 (결과) {// 집계 결과 CONSOLE.LOG (+ results.length "모든 응답이 수신"); CONSOLE.LOG (JSON.stringify (결과, NULL, 2)); } , 기능 (오류) {// 오류 CONSOLE.LOG (에러); }) ///// }, 기능 (오류) {// 오류 CONSOLE.LOG (에러); });

    나는 광범위하게 여기에이 솔루션을 논의했다.


  16. 16.짧은 대답은이 같은 콜백을 구현해야한다 :

    짧은 대답은이 같은 콜백을 구현해야한다 :

    function callback(response) {
        // Here you can do what ever you want with the response object.
        console.log(response);
    }
    
    $.ajax({
        url: "...",
        success: callback
    });
    

  17. 17.이것은 매우 간단합니다 :

    이것은 매우 간단합니다 :

    여기에 코드의 작업 버전입니다 :

    (async function(){
    
    var response = await superagent.get('...')
    console.log(response)
    
    })()
    

    AWAIT은 현재의 모든 브라우저와 노드 8에서 지원됩니다


  18. 18.브라우저는 세 부분으로 나눌 수 있습니다 :

    브라우저는 세 부분으로 나눌 수 있습니다 :

    1) 이벤트 루프

    2) 웹 API

    3) 이벤트 대기열

    이벤트 루프, 즉 일종의 무한 loop.Event 큐의 영원히 동안 실행 모든 기능이 몇 가지 이벤트에 밀려 경우 (예 : 클릭)이 큐의 수행 하나 하나이며,이 기능을 실행하고 그것을 자신을 준비 이벤트 루프에 넣어 제 한 후 다음의 하나 하나 개의 기능 executed.This 수단은 실행을 위해 대기열 이벤트 루프에서 실행 전에 그것의 기능까지 시작하지 않는다.

    이제 우리가 data.We가 큐에 먼저 utiliseData () 함수를 ServerRequest에 () 함수를 추진하는 큐 하나의 서버에서 데이터를 다른 분류기를 얻기위한 두 가지 기능을 밀어 생각해 봅시다. ServerRequest에 기능 이벤트 루프에 간다 우리는 결코이 서버에서 데이터를 얻기 위해 소요되는 많은 시간을 알 수 없기 때문에 서버를 호출한다 그래서이 과정은 시간이 걸릴 것으로 예상되며, 우리 바쁜 우리의 이벤트 루프 따라서 웹 API 무료 그래서 우리는에서 다음 기능을 실행할 수있는이 이벤트 루프를 만드는 이벤트 루프와 서버와의 거래에서이 기능을 역할에 와서 어디 우리의 페이지를 걸려 큐에 queue.The 다음 기능은 루프에 간다하지만 때문에 사용할 수없는 데이터가 폐기물과 다음 함수의 실행 큐의 마지막까지 계속 간다 utiliseData ()입니다. (이것은 비동기 우리가 우리까지 다른 일을 할 수있는 예를 호출이라고합니다 ) 데이터를 얻을 수

    우리가 큐의 끝에서 큐에 밀어 것입니다 서버 웹 API에서 데이터를 다시 얻을 때 우리 ServerRequest에 () 함수, 코드에서 return 문을 있다고 가정하자. 이 큐의 끝에서 얻을수로 비동기 호출에서 뭔가를 반환 할 수없는이 data.Thus을 활용하는 우리의 큐에 남아있는 기능이 없기 때문에 우리는 데이터를 이용할 수 없습니다.

    따라서 이에 대한 해결 방법은 콜백 또는 약속이다.

    답변 중 하나에서 이미지 여기, 올바르게 콜백 사용 설명 ... 우리는 함수를 호출하는 서버에 대한 우리의 기능 (서버에서 반환 된 기능을 활용하여 데이터를) 제공합니다.

     function doAjax(callbackFunc, method, url) {
      var xmlHttpReq = new XMLHttpRequest();
      xmlHttpReq.open(method, url);
      xmlHttpReq.onreadystatechange = function() {
    
          if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
            callbackFunc(xmlHttpReq.responseText);
          }
    
    
      }
      xmlHttpReq.send(null);
    
    }
    

    내 코드에서 그것은라고한다

    function loadMyJson(categoryValue){
      if(categoryValue==="veg")
      doAjax(print,"GET","http://localhost:3004/vegetables");
      else if(categoryValue==="fruits")
      doAjax(print,"GET","http://localhost:3004/fruits");
      else 
      console.log("Data not found");
    }
    

    Javscript.info 콜백


  19. 19.당신은 원격 호출을 만들기 위해 (약속을 사용하여 작성)이 사용자 지정 라이브러리를 사용할 수 있습니다.

    당신은 원격 호출을 만들기 위해 (약속을 사용하여 작성)이 사용자 지정 라이브러리를 사용할 수 있습니다.

    function $http(apiConfig) {
        return new Promise(function (resolve, reject) {
            var client = new XMLHttpRequest();
            client.open(apiConfig.method, apiConfig.url);
            client.send();
            client.onload = function () {
                if (this.status >= 200 && this.status < 300) {
                    // Performs the function "resolve" when this.status is equal to 2xx.
                    // Your logic here.
                    resolve(this.response);
                }
                else {
                    // Performs the function "reject" when this.status is different than 2xx.
                    reject(this.statusText);
                }
            };
            client.onerror = function () {
                reject(this.statusText);
            };
        });
    }
    

    간단한 사용 예 :

    $http({
        method: 'get',
        url: 'google.com'
    }).then(function(response) {
        console.log(response);
    }, function(error) {
        console.log(error)
    });
    

  20. 20.또 다른 방법은 순차적 실행기 nsynjs 통해 코드를 실행하는 것이다.

    또 다른 방법은 순차적 실행기 nsynjs 통해 코드를 실행하는 것이다.

    nsynjs 순차적으로 모든 약속을 평가하고, 데이터 속성에 넣어 약속의 결과 것입니다 :

    synchronousCode 함수 () { VAR의 getURL = 기능 (URL) { 반환 window.fetch (URL) .data.text () 데이터입니다.; }; var에 URL = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'; CONSOLE.LOG가 ( '바이트를받은 :'의 getURL (URL) .length); }; nsynjs.run (synchronousCode {} 함수 () { 을 console.log ( 'synchronousCode 완료'); }); <스크립트 SRC = "https://rawgit.com/amaksr/nsynjs/master/nsynjs.js">

    nsynjs 인식 래퍼로 콜백 1. 랩 기능을 단계 (이 버전을 promisified 경우,이 단계를 건너 뛸 수 있습니다) :

    var ajaxGet = function (ctx,url) {
        var res = {};
        var ex;
        $.ajax(url)
        .done(function (data) {
            res.data = data;
        })
        .fail(function(e) {
            ex = e;
        })
        .always(function() {
            ctx.resume(ex);
        });
        return res;
    };
    ajaxGet.nsynjsHasCallback = true;
    

    2 단계는 함수에 동기 로직을 ​​넣어 :

    function process() {
        console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
    }
    

    nsynjs를 통해 동기 방식 3. 실행 기능을 단계 :

    nsynjs.run(process,this,function () {
        console.log("synchronous function finished");
    });
    

    Nsynjs 모든 사업자와 표현을 단계별로, 일부 느린 함수의 결과가 준비되지 않은 경우 경우 실행을 일시 중지 평가합니다.

    여기에 더 많은 예제 : https://github.com/amaksr/nsynjs/tree/master/examples


  21. 21.ECMAScript를 6은 비동기적인 스타일로 쉽게 프로그램을 수있는 '발전기'를 가지고있다.

    ECMAScript를 6은 비동기적인 스타일로 쉽게 프로그램을 수있는 '발전기'를 가지고있다.

    function* myGenerator() {
        const callback = yield;
        let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
        console.log("response is:", response);
    
        // examples of other things you can do
        yield setTimeout(callback, 1000);
        console.log("it delayed for 1000ms");
        while (response.statusText === "error") {
            [response] = yield* anotherGenerator();
        }
    }
    

    이렇게 위의 코드를 실행하려면 :

    const gen = myGenerator(); // Create generator
    gen.next(); // Start it
    gen.next((...args) => gen.next([...args])); // Set its callback function
    

    당신이 ES6를 지원하지 않는 브라우저를 대상으로해야하는 경우 인 ECMAScript 5를 생성하기 위해 바벨 또는 폐쇄 컴파일러를 통해 코드를 실행할 수 있습니다.

    콜백은 ... args는 배열에 싸여하고 패턴이 여러 인수를 콜백에 대응할 수 있도록 읽을 때 탈구된다. 노드 FS와 예를 들면 :

    const [err, data] = yield fs.readFile(filePath, "utf-8", callback);
    

  22. 22.VAR 앱은 앱을 = || {}; 앱 = { getDataFromServer : 함수 () { VAR 자체는,이 = 연기 = $ .Deferred () 요청 = []; (. $해서 getJSON ( '요청 / 아약스 / URL / 1')) requests.push; (. $해서 getJSON ( '요청 / 아약스 / URL / 2')) requests.push; .when.apply $ (jQuery를 요청)되는 .done (기능 (xhrResponse) { 리턴 deferred.resolve (xhrResponse.result); }); 연기 반환; }, 초기화하기 : 함수 () { this.getDataFromServer (). (일 _. 바인드 (함수 (resp1, resp2) { 당신이 원하는 // 수행 작업은 때를 수행하는 // 예를 들어 아약스의 응답, 로그 응답을 얻을. }, 이)); } }; () App.init;

    VAR 앱은 앱을 = || {}; 앱 = { getDataFromServer : 함수 () { VAR 자체는,이 = 연기 = $ .Deferred () 요청 = []; (. $해서 getJSON ( '요청 / 아약스 / URL / 1')) requests.push; (. $해서 getJSON ( '요청 / 아약스 / URL / 2')) requests.push; .when.apply $ (jQuery를 요청)되는 .done (기능 (xhrResponse) { 리턴 deferred.resolve (xhrResponse.result); }); 연기 반환; }, 초기화하기 : 함수 () { this.getDataFromServer (). (일 _. 바인드 (함수 (resp1, resp2) { 당신이 원하는 // 수행 작업은 때를 수행하는 // 예를 들어 아약스의 응답, 로그 응답을 얻을. }, 이)); } }; () App.init;


  23. 23.우리는 우리가 "시간"전화 치수를 따라 진행 보이는 우주에서 자신을 찾을 수 있습니다. 우리는 정말 시간이 무엇인지 이해하지 않지만, 우리는 그것에 대해 우리에게 이성과 이야기를하자 추상화과 어휘 개발했다 : "미래", "과거" "현재", "후" "전에"를.

    우리는 우리가 "시간"전화 치수를 따라 진행 보이는 우주에서 자신을 찾을 수 있습니다. 우리는 정말 시간이 무엇인지 이해하지 않지만, 우리는 그것에 대해 우리에게 이성과 이야기를하자 추상화과 어휘 개발했다 : "미래", "과거" "현재", "후" "전에"를.

    컴퓨터 시스템은 우리가 구축 - 더 - 중요한 차원으로 시간을 가지고있다. 어떤 일이 미래에 일어날 설정되어 있습니다. 그런 다음 다른 일이 그 첫 번째 일이 결국 발생 후 발생합니다. 이것은 "비 동시성"라는 기본 개념이다. 점점 더 네트워크화 된 세계에서 비 동시성의 가장 일반적인 경우는 일부 요청에 응답 일부 원격 시스템을 기다리고 있습니다.

    예를 생각해 보자. 당신은 우유 배달부를 호출하고 우유를 주문하십시오. 그것이 올 때, 당신은 당신의 커피에 넣어합니다. 그것은 아직 여기에 있기 때문에 당신은 지금 당신의 커피에 우유를 넣어 수 없습니다. 당신은 커피에 넣어 전에 오기를 기다려야한다. 즉, 다음은 작동하지 않습니다 :

    var milk = order_milk();
    put_in_coffee(milk);
    

    JS는 그것이 put_in_coffee을 실행하기 전에 마무리 order_milk 기다릴 필요가 있음을 알 수있는 방법이 없기 때문입니다. 즉,이 order_milk 비동기 것을 알고하지 않습니다 - 미래의 어느 시간까지 우유를 초래하지 않을 무언가이다. JS, 그리고 다른 선언적 언어 기다리지 않고 연이어 문을 실행합니다.

    고전 JS 주위에 전달 될 수 일류 개체, 그 다음이 완료된 호출하는 비동기 요청을 파라미터로하는 함수를 전달하는 것처럼 JS가 기능을 지원한다는 점을 이용하는 방법이 문제에 접근 앞으로의 작업 언젠가. 즉, "콜백"접근 방식입니다. 그것은 다음과 같습니다 :

    order_milk(put_in_coffee);
    

    order_milk 킥 오프, 주문 우유, 다음, 언제가 도착하는 경우에만,이 put_in_coffee를 호출합니다.

    이 콜백 방식의 문제는 창으로 그 결과를보고하는 기능의 일반적인 의미를 오염이다; 대신, 기능을해야하지 매개 변수로 주어진 콜백을 호출하여 그 결과를보고합니다. 이벤트의 긴 시퀀스를 처리 할 때 또한,이 방법은 신속하게 다루기 될 수 있습니다. 예를 들어, 나는 우유가 커피에 넣어, 다음 만 다음 즉 커피를 마시는, 제 3 단계를 수행 할 때까지 대기 할 것을 가정 해 봅시다. 이 같은 쓰기 뭔가 필요 결국 :

    order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }
    

    나는 우유에 넣어 일단 실행하기 위해 그 안에 넣어 우유, 또한 행동 (drink_coffee) 모두 put_in_coffee을 통과하고 어디에. 이러한 코드는 쓰기 하드되고, 읽고, 디버그.

    이 경우, 우리는 질문으로의 코드를 다시 작성할 수 있습니다 :

    var answer;
    $.ajax('/foo.json') . done(function(response) {
      callback(response.data);
    });
    
    function callback(data) {
      console.log(data);
    }
    

    이것은 미래의 또는 어떤 종류의 비동기 결과를 나타내는 값의 특정 유형 인 "약속"의 개념에 대한 동기를 부여했다. 이미 일어난 일을 나타낼 수, 또는 미래에 일어날 것입니다, 또는 전혀 발생하지 않을 수도 있습니다. 약속은 약속이 나타내는 결과가 실현되었을 때 당신이 작업을 통과되는 후라는 하나의 메소드가 실행되어야한다.

    우리 우유와 커피의 경우, 우리는 다음과 같이하고, 도착 우유에 대한 약속을 돌려 다음 작업으로 put_in_coffee을 지정 order_milk 설계 :

    order_milk() . then(put_in_coffee)
    

    이것의 장점 중 하나는 우리가 문자열이 함께합니다 ( "체인") 미래 발생의 시퀀스를 만들 수 있다는 것입니다 :

    order_milk() . then(put_in_coffee) . then(drink_coffee)
    

    의는 특정 문제에 약속을 적용 할 수 있습니다. 우리는 약속을 반환하는 함수 내부에 우리의 요청 논리를 포장한다 :

    function get_data() {
      return $.ajax('/foo.json');
    }
    

    사실, 우리가 한 모든 $ 아약스 호출에 반환을 추가한다. jQuery의 $ 아약스가 이미 약속 같은 일의 종류를 반환하기 때문에이 작동합니다. (실제로, 세부 사항에 들어가기없이, 우리는 반환로 진짜 약속 때문에이 호출을 포장, 또는 그렇게 그 $ 아약스 몇 가지 대안을 사용하는 것을 선호합니다.) 이제, 우리는 그것을 위해 파일 및 대기를로드 할 경우 마무리로하고 무언가를, 우리는 간단하게 말할 수있다

    get_data() . then(do_something)
    

    예를 들어,

    get_data() . 
      then(function(data) { console.log(data); });
    

    약속을 사용하는 경우는 더욱 컴팩트 ES6 스타일의 화살표 기능을 사용하는 것이 도움이 그래서, 우리는 그 다음으로 많은 기능을 전달 결국 :

    get_data() . 
      then(data => console.log(data));
    

    하지만 여전히 막연하게 코드를 작성 한 동기 경우 방법과 매우 다른 방식으로 비동기 경우를하는 것에 대한 만족스럽지 뭔가가있다. 동기, 우리는 쓰기

    a();
    b();
    

    A는 약속과 함께, 비동기 경우 그러나 우리는 작성해야

    a() . then(b);
    

    위, 우리는 "JS는 그것이 두 번째를 실행하기 전에 마무리에 대한 첫 번째 호출을 기다릴 필요가 있음을 알 수있는 방법이 없다"고 말했다. 것을 JS를 알 수있는 방법이 있다면 그것은 좋은를하지 않을까요? 기능 특수한 유형의 내부에 사용되는 await를 키워드,에 "비동기"함수를 호출 -이 있다는 것을 밝혀졌습니다. 이 기능은 ES의 향후 버전의 일부 있지만, 올바른 사전 제공 등의 바벨과 같은 transpilers에서 이미 사용할 수 있습니다. 이것은 단순히 쓰기 우리를 수

    async function morning_routine() {
      var milk   = await order_milk();
      var coffee = await put_in_coffee(milk);
      await drink(coffee);
    }
    

    귀하의 경우에는, 당신은 같은 것을 쓸 수있을 것

    async function foo() {
      data = await get_data();
      console.log(data);
    }
    

  24. 24.짧은 답변 : 귀하의 foo는 () 메소드가 반환 즉시 동안 비동기 함수가 반환 후 $ 아약스 () 호출을 실행합니다. 문제는 어디에서 어떻게이 반환되면 비동기 호출에 의해 검색 결과를 저장하는 것입니다.

    짧은 답변 : 귀하의 foo는 () 메소드가 반환 즉시 동안 비동기 함수가 반환 후 $ 아약스 () 호출을 실행합니다. 문제는 어디에서 어떻게이 반환되면 비동기 호출에 의해 검색 결과를 저장하는 것입니다.

    몇 가지 솔루션은이 스레드에 주어졌다. 아마도 가장 간단한 방법은 푸 () 메소드에 객체를 전달하기 위해, 상기 비동기 호출이 완료된 후에 해당 개체의 부재의 결과를 저장하는 것이다.

    function foo(result) {
        $.ajax({
            url: '...',
            success: function(response) {
                result.response = response;   // Store the async result
            }
        });
    }
    
    var result = { response: null };   // Object to hold the async result
    foo(result);                       // Returns before the async completes
    

    foo는 ()에 대한 호출은 여전히 ​​유용한 아무 것도 반환하지 않습니다. 그러나, 비동기 호출의 결과는 지금 result.response에 저장됩니다.


  25. 25.foo는 () 성공 내부 콜백 () 함수를 사용합니다. 이 방법으로 시도하십시오. 그것은 간단하고 이해하기 쉽다.

    foo는 () 성공 내부 콜백 () 함수를 사용합니다. 이 방법으로 시도하십시오. 그것은 간단하고 이해하기 쉽다.

    var lat = "";
    var lon = "";
    function callback(data) {
        lat = data.lat;
        lon = data.lon;
    }
    function getLoc() {
        var url = "http://ip-api.com/json"
        $.getJSON(url, function(data) {
            callback(data);
        });
    }
    
    getLoc();
    

  26. 26.이 질문에 대한 가장 완벽한 대답은 약속을 사용하고 있습니다.

    이 질문에 대한 가장 완벽한 대답은 약속을 사용하고 있습니다.

    function ajax(method, url, params) {
      return new Promise(function(resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.onload = function() {
          resolve(this.responseText);
        };
        xhr.onerror = reject;
        xhr.open(method, url);
        xhr.send(params);
      });
    }
    
    ajax("GET", "/test", "acrive=1").then(function(result) {
        // Code depending on result
    })
    .catch(function() {
        // An error occurred
    });
    

    약속을 사용하여 문제가 있습니다!

    나는 오래된 브라우저에 오류가 파악 될 때까지 나는 잠시 동안이 솔루션을 사용하고 있었다 :

    Uncaught ReferenceError: Promise is not defined
    

    그래서 나는 그것의 정의되지 않은 경우 JS 컴파일러 아래에 ES3에 대한 내 자신의 약속 클래스를 구현하기로 결정했다. 그냥 기본 코드 앞에이 코드를 추가 한 다음 안전하게 약속을 사용!

    if(typeof Promise === "undefined"){
        function _classCallCheck(instance, Constructor) {
            if (!(instance instanceof Constructor)) { 
                throw new TypeError("Cannot call a class as a function"); 
            }
        }
        var Promise = function () {
            function Promise(main) {
                var _this = this;
                _classCallCheck(this, Promise);
                this.value = undefined;
                this.callbacks = [];
                var resolve = function resolve(resolveValue) {
                    _this.value = resolveValue;
                    _this.triggerCallbacks();
                };
                var reject = function reject(rejectValue) {
                    _this.value = rejectValue;
                    _this.triggerCallbacks();
                };
                main(resolve, reject);
            }
            Promise.prototype.then = function then(cb) {
                var _this2 = this;
                var next = new Promise(function (resolve) {
                    _this2.callbacks.push(function (x) {
                        return resolve(cb(x));
                    });
                });
                return next;
            };
            Promise.prototype.catch = function catch_(cb) {
                var _this2 = this;
                var next = new Promise(function (reject) {
                    _this2.callbacks.push(function (x) {
                        return reject(cb(x));
                    });
                });
                return next;
            };
            Promise.prototype.triggerCallbacks = function triggerCallbacks() {
                var _this3 = this;
                this.callbacks.forEach(function (cb) {
                    cb(_this3.value);
                });
            };
            return Promise;
        }();
    }
    

  27. 27.질문이었다 :

    질문이었다 :

    로 해석 될 수있다 :

    용액 콜백을 피하고, 약속과 비동기 / AWAIT의 조합을 사용하는 것이다.

    나는 Ajax 요청에 대한 예를 제공하고 싶습니다.

    (이 자바 스크립트로 작성 될 수 있지만, 파이썬에서 작성 선호하고, 번역하기를 사용하여 자바 스크립트로 컴파일합니다. 그것은 분명 충분합니다.)

    첫째 S로 $ 사용할 수를 가지고, JQuery와 사용을 가능하게 할 수 있습니다 :

    __pragma__ ('alias', 'S', '$')
    

    이 경우 Ajax 호출에, 약속을 반환하는 함수를 정의합니다 :

    def read(url: str):
        deferred = S.Deferred()
        S.ajax({'type': "POST", 'url': url, 'data': { },
            'success': lambda d: deferred.resolve(d),
            'error': lambda e: deferred.reject(e)
        })
        return deferred.promise()
    

    이 동기 것처럼 비동기 코드를 사용 :

    async def readALot():
        try:
            result1 = await read("url_1")
            result2 = await read("url_2")
        except Exception:
            console.warn("Reading a lot failed")
    

  28. 28.물론 동기 요청, 약속 같은 많은 방법이 있습니다,하지만 내 경험에서 나는 당신이 콜백 방식을 사용한다고 생각합니다. 그것은 자바 스크립트의 비동기 동작과 자연입니다. 그래서, 당신의 코드는 조금 다른를 다시 작성할 수 있습니다 :

    물론 동기 요청, 약속 같은 많은 방법이 있습니다,하지만 내 경험에서 나는 당신이 콜백 방식을 사용한다고 생각합니다. 그것은 자바 스크립트의 비동기 동작과 자연입니다. 그래서, 당신의 코드는 조금 다른를 다시 작성할 수 있습니다 :

    function foo() {
        var result;
    
        $.ajax({
            url: '...',
            success: function(response) {
                myCallback(response);
            }
        });
    
        return result;
    }
    
    function myCallback(response) {
        // Does something.
    }
    

  29. 29.여기 내 경험을 모두 응답을 읽은 후, 나는의 세부 사항을 다시 시작하고 싶습니다 콜백, 자바 스크립트에서 비동기 프로그래밍 비동기 / await를 약속합니다.

    여기 내 경험을 모두 응답을 읽은 후, 나는의 세부 사항을 다시 시작하고 싶습니다 콜백, 자바 스크립트에서 비동기 프로그래밍 비동기 / await를 약속합니다.

    1) 콜백 : 콜백에 대한 근본적인 이유는 (아래의 예를 참조) 이벤트에 응답하여 코드를 실행한다. 우리는 자바 스크립트 때마다 콜백을 사용합니다.

    const body = document.getElementsByTagName('body')[0];
    function callback() {
      console.log('Hello');
    }
    body.addEventListener('click', callback);
    

    아래의 예에서 많은 중첩 된 콜백을 사용해야하는 경우, 그것은 코드 리팩토링에 대한 끔찍한 요정 될 것입니다.

    asyncCallOne(function callback1() {
      asyncCallTwo(function callback2() {
        asyncCallThree(function callback3() {
            ...
        })
      })
    })
    

    2) 약속 : 구문 ES6 - 약속 콜백 지옥 문제를 해결!

    const myFirstPromise = new Promise((resolve, reject) => {
      // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
      // In this example, we use setTimeout(...) to simulate async code. 
      // In reality, you will probably be using something like XHR request or an HTML5 API.
      setTimeout(() => {
        resolve("Success!")  // Yay! Everything went well!
      }, 250)
    }) 
    
    myFirstPromise
      .then((res) => {
        return res.json();
      })
      .then((data) => {
        console.log(data);
      })
      .catch((e) => {
        console.log(e);
      });
    

    myFirstPromise 비동기 코드 프로세스를 나타낸다 약속 인스턴스이다. 결의 기능 신호는 약속 인스턴스가 완료되었는지. 이후, 우리는 약속 인스턴스 (그 때는 체인 당신이 원하는대로) 및 .catch ()) (그 때는 호출 할 수 있습니다 :

    then — Runs a callback you pass to it when the promise has fulfilled.
    catch — Runs a callback you pass to it when something went wrong.
    

    3) 비동기 / 기다리고 있습니다 : 새 구문 ES6 - 기다리고 있습니다 기본적으로 약속의 설탕 구문입니다!

    비동기 기능은 우리가 약속 얻는 것과 같은 결과를 달성하기 위해 더 적은 코드를 작성할 수있는 깨끗하고 간결한 구문으로 우리를 제공합니다. 비동기 / 기다리고 있습니다 동기 코드와 비슷하고, 동기 코드는 읽기 및 쓰기 훨씬 쉽습니다. 비동기 / 기다리고 있습니다로 캐치 오류에, 우리는 블록 시도 ... 캐치를 사용할 수 있습니다. 여기에서, 당신은 약속 구문 그 때는 체인 ()를 작성할 필요가 없습니다.

    const getExchangeRate = async () => {
      try {
        const res = await fetch('https://getExchangeRateData');
        const data = await res.json();
        console.log(data);
      } catch (err) {
        console.error(err);
      }
    }
    
    getExchangeRate();
    

  30. 30.오히려 당신의 코드를 던지는 것보다, JS 콜백 및 비동기 성을 처리하는 방법을 이해하는 데 핵심이 개 개념이있다. (심지어 단어이다?)

    오히려 당신의 코드를 던지는 것보다, JS 콜백 및 비동기 성을 처리하는 방법을 이해하는 데 핵심이 개 개념이있다. (심지어 단어이다?)

    당신이 알아야 할 세 가지가 있습니다; 큐; 이벤트 루프 스택

    넓은에서, 단순한 용어는 이벤트 루프는 지속적으로 큐와 스택 사이에 실행하려는 기능과 통신하는을 수신하고, 프로젝트 관리자 같다.

    while (queue.waitForMessage()) {
       queue.processNextMessage();
    }
    

    이 실행 뭔가 메시지를 수신하면이 대기열에 추가합니다. 큐는 (당신의 AJAX 요청 등) 실행하기 위해 대기중인 것들의 목록입니다. 이런 식으로 상상 :

     1. call foo.com/api/bar using foobarFunc
     2. Go perform an infinite loop
     ... and so on
    

    이들 중 하나의 메시지는 큐로부터 메시지를 나타나고 스택을 작성 실행하려고 할 때, 스택은 JS는 메시지의 명령을 수행하기 위해 실행할 필요가있는 모든 것이다. 그래서 우리의 예에서이 foobarFunc 전화를했다되고 있어요

    function foobarFunc (var) {
      console.log(anotherFunction(var));
    }
    

    foobarFunc 요구가 실행하는 것을 아무것도 그래서 (우리의 경우 anotherFunction에) 스택으로 푸시 얻을 것이다. 이벤트 루프는 다음 큐의 다음 일에 이동 (또는 메시지를 수신)합니다 - 실행 한 다음 잊어

    여기서 중요한 것은 실행의 순서입니다. 그건

    외부 파티에 AJAX를 사용하여 전화를 걸거나 비동기 코드 (예를 들면에서는 setTimeout)를 실행하면 진행하기 전에, 자바 스크립트는 응답에 따라 달라집니다.

    이 응답을 얻을 때 큰 문제는? 이벤트 루프는 "이봐, 나를 실행"말을 그 메시지를 기다리는 때문에 - 그 대답은 우리가 모르는 것입니다. JS 그냥 메시지를 주위에 기다렸다 경우 동 기적으로 앱 동결 그것은 빨아 것입니다. 그래서 JS는 메시지가 다시 큐에 추가됩니다 때까지 대기하는 동안 큐의 다음 항목을 실행에 전달한다.

    비동기 기능을 우리가 콜백라는 것을 사용하는 이유입니다. 그것은 말 그대로 일종의 약속처럼. 나는 어떤 시점에서 뭔가를 반환 할 것을 약속에서와 같이 jQuery를이 deffered.done의 deffered.fail과 (다른 사람의 사이에) deffered.always라는 특정 콜백을 사용합니다. 당신은 모두 여기에 그들을 볼 수 있습니다

    그래서 당신이해야 할 것은에 전달되는 데이터에 몇 가지 점에서 실행 약속 함수를 전달합니다.

    콜백이 즉시 실행하지만 나중에는 함수에 대한 참조를 전달하는 것이 중요하지 않기 때문에하지 그것을 실행. 그래서

    function foo(bla) {
      console.log(bla)
    }
    

    그래서 대부분의 시간 (항상은 아니지만) 당신은 () foo는하지 foo는 정보를 전달하겠습니다

    희망이 어떤 의미를 만들 것입니다. 당신이 혼란 것 같은 일이 발생하면 - 내가보기 엔 그것의 이해를 얻을 적어도에 완전히 설명서를 읽어 보시기 바랍니다. 그것은 당신이 더 나은 개발자가 만들 것입니다.

  31. from https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call by cc-by-sa and MIT license