2017-11-30 13 views
0

다음 코드에서 100000 레코드 recursiveFnReturnsPromiseV1은 스택 외부 예외로 인해 실패하지만 recursiveFnReturnsPromiseV1은 잘 실행됩니다. 두 가지의 유일한 차이점은 약속이 재발되는 방식입니다. v1에서 재귀는 첫 번째 약속의 "그 다음"내에 있고 v2에서는 재귀가 원래 약속 자체 내에 있습니다. 차이점이 뭐야?약속을 반환하는 재귀 JavaScript 함수를 호출하는 패턴을 다음과 같이 사용하는 경우의 차이점은 무엇입니까?

let aValues = Array(100000); 
 

 

 
recursiveFnReturnsPromiseV1(aValues, 0).then(function() { 
 
    let p = document.createElement('div'); 
 
    p.innerText = 'recursiveFnReturnsPromiseV1 finished'; 
 
    document.getElementById('v1').appendChild(p); 
 
}, function() { 
 
    let p = document.createElement('div'); 
 
    p.innerText = 'recursiveFnReturnsPromiseV1 failed'; 
 
    document.getElementById('v1').appendChild(p); 
 
}) 
 

 
recursiveFnReturnsPromiseV2(aValues, 0) 
 
    .then(function() { 
 
    let p = document.createElement('div'); 
 
    p.innerText = 'recursiveFnReturnsPromiseV2 finished'; 
 
    document.getElementById('v2').appendChild(p); 
 
    }, function() { 
 
    let p = document.createElement('div'); 
 
    p.innerText = 'recursiveFnReturnsPromiseV2 failed'; 
 
    document.getElementById('v2').appendChild(p); 
 
    }) 
 

 
function recursiveFnReturnsPromiseV1(pValues, ix) { 
 
    if (pValues.length <= ix) 
 
    return Promise.resolve(); 
 

 
    return new Promise(function(c, e) { 
 
    document.getElementById('v1').innerText = ix + 'v1' + Date.now(); 
 
    c(); 
 
    }).then(function() { 
 
    return recursiveFnReturnsPromiseV1(pValues, ++ix); 
 
    }) 
 

 

 

 
} 
 

 
function recursiveFnReturnsPromiseV2(pValues, ix) { 
 
    if (pValues.length <= ix) 
 
    return Promise.resolve(); 
 

 

 
    return new Promise(function(c, e) { 
 
    document.getElementById('v2').innerText = ix + 'v2' + Date.now(); 
 

 
    recursiveFnReturnsPromiseV2(pValues, ++ix).then(function() { 
 
     c(); 
 
    }, function(err) { 
 
     e() 
 
    }); 
 
    }) 
 
}
<div id='v1'></div> 
 
<div id='v2'></div>

+1

v1, 재귀가 비동기 적으로 수행됩니다 ('.then') ... 재귀가 아닙니다 ... Promise 생성자의 코드가 동기입니다 ... note : 코드를 읽기가 어렵습니다. 겉보기 임의의 들여 쓰기 –

+0

레벨 당 들여 쓰기의 공간을 하나만 사용하는 코드를 실제로 찾으십니까? 나는하지 않는다. 그것을 읽을 수 없습니다. 여기에 표시된대로 이해할 수 없습니다. 코드가 읽기 어려운 질문에 시간을 낭비하지 않아도됩니다. – jfriend00

+1

@ jfriend00 -'recursiveFnReturnsPromiseV2' 함수를 보면, 첫 번째 코드는 4만큼 들여 쓰입니다. 반환 값은 2만큼 들여 쓰기되고 약속 실행자의 첫 번째 줄 또한 2만큼 들여 쓰여집니다. 다음 두 줄은 1만큼 들여 쓰기되어 있기 때문에 블럭에 관해서는 "outdented"되어 있습니다. 내가 언급했듯이 실제로는 무작위입니다. (파이어 폭스 스크래치 패드에 복사/붙여 넣기가 쉽지만 : p) –

답변

1

Promise constructor antipattern을 벗겨, 대신 간단한 Promise.resolve을 사용할 수 있습니다. 귀하의 기능은 이제

function recursiveFnReturnsPromiseV1(pValues, ix) { 
    if (pValues.length <= ix) 
    return Promise.resolve(); 

    let p = document.createElement('div'); 
    p.innerText = ix + 'v1' + Date.now(); 
    document.getElementById('v1').appendChild(p); 

    return Promise.resolve().then(function() { 
    return recursiveFnReturnsPromiseV1(pValues, ++ix); 
    }) 
} 

function recursiveFnReturnsPromiseV2(pValues, ix) { 
    if (pValues.length <= ix) 
    return Promise.resolve(); 

    let p = document.createElement('div'); 
    p.innerText = ix + 'v2' + Date.now(); 
    document.getElementById('v2').appendChild(p); 

    return Promise.resolve(recursiveFnReturnsPromiseV2(pValues, ++ix)); 
} 

그것은 두 번째 기능은 스택 오버플로 지금 이유가 분명해야된다.

왜 첫 번째도 좋지 않은가요? 재귀 호출은 비동기then 콜백 내부에 있으므로 외부 호출이 반환 된 후 나중에 시작되어 새로운 호출 스택으로 시작됨을 의미합니다.