JavaScript에서 then () 함수는 무엇을 의미합니까?


답변:


348

JavaScript에서 비동기 호출을 처리하는 전통적인 방법은 콜백입니다. 응용 프로그램을 설정하기 위해 서버를 차례로 세 번 호출해야한다고 가정 해 봅시다. 콜백을 사용하면 코드가 다음과 같이 보일 수 있습니다 (서버 호출을위한 xhrGET 함수 가정).

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

이 예에서는 먼저 서버 구성을 가져옵니다. 그런 다음이를 바탕으로 현재 사용자에 대한 정보를 가져온 다음 마지막으로 현재 사용자의 항목 목록을 가져옵니다. 각 xhrGET 호출은 서버가 응답 할 때 실행되는 콜백 함수를 사용합니다.

물론 더 많은 수준의 중첩이있을수록 코드를 읽고, 디버깅하고, 유지 관리하고, 업그레이드하고, 기본적으로 작업하기가 더 어렵습니다. 이것을 일반적으로 콜백 지옥이라고합니다. 또한 오류를 처리해야하는 경우 각 xhrGET 호출에 다른 함수를 전달하여 오류 발생시 수행해야 할 작업을 알려야합니다. 일반적인 오류 처리기를 하나만 원한다면 불가능합니다.

Promise API는 이러한 중첩 문제와 오류 처리 문제를 해결하도록 설계되었습니다.

Promise API는 다음을 제안합니다.

  1. 각 비동기 작업은 promise개체 를 반환 합니다.
  2. promise객체 then에는 success 핸들러와 error핸들러 라는 두 개의 인수를 사용할 수 있는 함수가 있습니다 .
  3. 비동기 작업이 완료된 후 함수 의 성공 또는 오류 처리기가 한 번만then 호출됩니다 .
  4. then함수는 또한 promise여러 호출을 연결하기 위해를 반환 합니다.
  5. 각 핸들러 (성공 또는 오류)는을 리턴 할 수 있으며 value,이 argument체인은 promises 체인에서 으로 다음 함수에 전달됩니다 .
  6. 핸들러가 a를 리턴하면 promise(다른 비동기 요청을 작성), 요청이 완료된 후에 만 ​​다음 핸들러 (성공 또는 오류)가 호출됩니다.

따라서 앞의 예제 코드는 promise와 $httpservice (AngularJs)를 사용하여 다음과 같은 것으로 변환 될 수 있습니다 .

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

전파 성공 및 오류

체이닝 약속은 서비스가 서버 호출을하고 데이터를 후 처리 한 다음 처리 된 데이터를 컨트롤러에 반환하는 등 많은 기능을 수행 할 수있는 매우 강력한 기술입니다. 그러나 promise체인으로 작업 할 때 명심해야 할 것이 몇 가지 있습니다.

promiseP1, P2 및 P3의 3 가지 약속이 있는 다음의 가상 체인을 고려하십시오 . 각각 promise에는 성공 처리기와 오류 처리기가 있으므로 P1의 경우 S1 및 E1, P2의 경우 S2 및 E2, P3의 경우 S3 및 E3이 있습니다.

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

오류가없는 정상적인 흐름에서는 응용 프로그램이 S1, S2 및 마지막으로 S3을 통과합니다. 그러나 실제 생활에서는 그렇게 매끄럽지 않습니다. P1에 오류가 발생하거나 P2에 오류가 발생하여 E1 또는 E2를 트리거 할 수 있습니다.

다음과 같은 경우를 고려하십시오.

• P1의 서버로부터 성공적으로 응답을 받았지만 반환 된 데이터가 정확하지 않거나 서버에 사용 가능한 데이터가 없습니다 (빈 배열이라고 생각). 이 경우 다음 약속 P2의 경우 오류 처리기 E2를 트리거해야합니다.

• 약속 P2에 대한 오류가 발생하여 E2가 트리거됩니다. 그러나 처리기 내부에는 캐시의 데이터가 있으므로 응용 프로그램이 정상적으로로드 될 수 있습니다. 이 경우 E2 이후에 S3이 호출되도록 할 수 있습니다.

따라서 성공 또는 오류 처리기를 작성할 때마다 호출해야합니다. 현재 기능이 제공되면 약속 체인의 다음 처리기에 대한 성공 또는 실패입니까?

체인의 다음 약속에 대한 성공 처리기를 트리거하려는 경우 성공 또는 오류 처리기에서 값을 반환하면됩니다.

반면에 체인에서 다음 약속에 대해 오류 처리기를 트리거하려는 경우 deferred객체 를 사용하고 해당 reject()메서드를 호출 하여이를 수행 할 수 있습니다

이제 지연된 대상은 무엇입니까?

jQuery의 지연된 객체는 나중에 비동기 적으로 완료되는 작업 단위를 나타냅니다. 작업 단위가 완료되면 deferred오브젝트를 분석하거나 실패하도록 설정할 수 있습니다.

deferred개체는 포함 promise개체를. promise오브젝트를 통해 작업 단위가 완료 될 때 수행 될 작업을 지정할 수 있습니다. promise객체 에 콜백 함수를 설정하면됩니다 .

Jquery에서 지연된 객체 : https://api.jquery.com/jquery.deferred/

AngularJs의 지연된 객체 : https://docs.angularjs.org/api/ng/service/ $ q


3
잘 쓰여졌습니다. 이를 통해 약속을 실제로 지킬 수있었습니다.
Ju66ernaut

두 번째 매개 변수 인 오류 처리기는 항상 선택 사항입니까?
1.21 기가 와트

이것은 지금까지 내가 본 최고의 답변입니다!
Imam Bux

78

then () 함수는 jQuery 또는 AngularJS와 같은 일부 라이브러리 또는 프레임 워크에서 사용되는 "자바 스크립트 약속"과 관련이 있습니다.

약속은 비동기 작업을 처리하기위한 패턴입니다. promise를 사용하면 콜백으로 사용할 함수를 지정할 수있는 "then"이라는 메서드를 호출 할 수 있습니다.

자세한 내용은 다음을 참조 하십시오 : http://wildermuth.com/2013/8/3/JavaScript_Promises

그리고 Angular 약속의 경우 : http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/


4
작업이 완료되면 실행되는 콜백과 같습니다. 어떻게 다른
가요

3
자바 스크립트는 약속 다른 코멘트는 말한다에 : A promise can only succeed or fail onceIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
샤오

또한 약속 너겟 은 사용 방법 promise과 수행 방법을 설명합니다callback
Xiao

첫 페이지에는 코드 덩어리가 없습니다 (큰 흰색 공백). 대부분의 사람들은 요소 검사를 생각하고 그 아래에서 바이올린의 URL을 찾습니다. 이 메시지는 나머지입니다 - 아직 일을 가지고 놀아)
DanteTheSmith

1
@MuhammadUmer : this stackoverflow.com/a/31453579/1350476 (Sid의 답변) 읽기
SharpCoder

32

내 지식 으로는 (이 글을 쓰는 시점에) 내장 then()방법 이 없습니다 javascript.

그것이 doSome("task")반환 하는 것은 무엇이든 이라는 메소드를 가지고있는 것으로 보입니다 then.

doSome()콘솔에 반환 결과를 기록하면 반환 된 내용의 속성을 볼 수 있어야합니다.

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

업데이트 (ECMAScript6 기준) :-

.then()함수는 순수 자바 스크립트에 포함되었습니다.

모질라 문서에서 여기 ,

then () 메서드는 Promise를 반환합니다. Promise의 성공 및 실패 사례에 대한 콜백 함수라는 두 가지 인수가 필요합니다.

Promise 객체는 다음과 같이 정의됩니다.

Promise 개체는 지연 및 비동기 계산에 사용됩니다. 약속은 아직 완료되지 않았지만 향후에 예상되는 작업을 나타냅니다.

즉, Promise아직 계산되지 않은 값의 자리 표시 자 역할을하지만 앞으로는 해결 될 것입니다. 그리고이 .then()함수는 Promise에서 호출 될 함수를 해결할 때 성공 또는 실패로 연결하는 데 사용됩니다.


12
당시에는 기본 제공 기능이 .then없었지만 ES6에서 기본 약속이 제공됩니다. html5rocks.com/en/tutorials/es6/promises
janfoeh

이 답변 덕분에 멋진 약속 콜백을 기대했지만 반환 된 'then'이라는 실제 함수로 판명되었습니다.
spartikus

15

여기에 내가 일하는 방식을 분명히하기 위해 만든 것이 있습니다. 다른 사람들 도이 구체적인 예를 유용하게 사용할 수 있다고 생각합니다.

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>


5

다음은 작은 JS_Fiddle입니다.

그런 다음 약속이 해결 된 후에 사용할 수있는 메소드 콜백 스택입니다 .jQuery와 같은 라이브러리의 일부이지만 이제는 네이티브 JavaScript로 사용할 수 있으며 작동 방법에 대한 자세한 설명은 다음과 같습니다

jQuery에 약속이있는 것처럼 모든 JavaScript를 약속대로 할 수 있습니다. 모든 약속을 쌓은 다음 콜백 확인 및 거부로 호출 할 수 있습니다. 이는 비동기 호출을 연결하는 방법입니다.

배터리 충전 상태에 대한 MSDN Docs에서 분기 및 편집했습니다.

이 작업은 사용자 랩톱 또는 장치가 배터리를 충전하고 있는지 확인하는 것입니다. 그런 다음 호출되고 당신은 당신의 작업 포스트 성공을 할 수 있습니다.

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

다른 es6 예

function fetchAsync (url, timeout, onData, onError) {
    
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

정의 :: 그런 다음 비동기 콜백을 해결하는 데 사용되는 방법입니다

이것은 ES6에 도입되었습니다

적절한 문서를 여기에서 찾으십시오. Es6 Promises


당신의 대답은 실제로 질문에 대답하지 않습니다. 어디에서 then왔으며 어떻게 작동하는지 설명하지 않고 API 사용법의 예만 제공합니다. 이러한 세부 정보를 제공하려면 답변을 개선해야합니다.
Didier L

@TarandeepSingh-먼저 배터리 상태를 경고하는 약속 개체는 반환되지 않습니다. 그렇다면 초의 사용은 무엇입니까
Mohit Jain

@MohitJain 새로운 약속이 없어도 여러 개의 콜백을 수행 할 수 있습니다. Promise.all을 사용하여 여러 통화를 수행 할 수도 있습니다.
Tarandeep Singh

" 메소드 콜백 스택 "이란 무엇입니까?
Bergi

4

doSome이 myObj 인 this를 반환한다고 생각합니다. 표준 방법 체인 ...

doSome이 이것을 반환하지 않으면 doSome이 실행 된 객체이므로 then 메소드를 사용하여 일부 객체를 반환합니다.

@ Patrick이 지적했듯이 표준 js에는 then ()이 없습니다.


1
나는 doSome이 이것을 반환한다고 의심한다 -그러한 의심을 강요하거나 정당화하는 것은 없다
Salathiel Genèse

1

doSome ( "task")는 promise 객체를 반환해야하며 그 promise에는 항상 then 함수가 있습니다. 따라서 코드는 다음과 같습니다

promise.then(function(env) {
    // logic
}); 

그리고 이것은 멤버 함수에 대한 일반적인 호출이라는 것을 알고 있습니다.


1

.then 비동기 함수에서 약속을 반환합니다.

좋은 예는 다음과 같습니다.

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

여기에 다른 로직을 추가하기 reject('I am the rejected param')위해 함수 호출 및 console.log를 추가 할 수도 있습니다 .


0

이 경우 then()메소드가 리턴 한 오브젝트의 클래스 메소드입니다 doSome().



-1

다른 예시:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

화살표 기능을 사용하는 동일한 논리를 속기 :

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)


-4

나는 약 8 년 늦었습니다. 어쨌든, 나는 then ()이 실제로 무엇을하는지 모르지만 MDN이 답을 가질 수 있습니다. 사실, 나는 그것을 조금 더 이해할 수 있습니다.

이것은 당신에게 필요한 모든 정보를 (희망스럽게) 보여줄 것입니다. 누군가이 링크를 이미 게시하지 않은 경우 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

형식은 promise.prototype.then () 약속과 프로토 타입은 변수와 비슷하지만 자바 스크립트의 변수와는 다릅니다. 다른 것들과 마찬가지로 navigator.getBattery (). then ()와 같이 실제로 존재하지만 웹에서 거의 사용되지 않는이 장치는 장치의 배터리 상태, 자세한 정보 및 궁금한 점이 있으면 MDN에 대한 정보를 표시합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.