단위 테스트를하고 있습니다. 테스트 프레임 워크는 페이지를 iFrame에로드 한 다음 해당 페이지에 대해 어설 션을 실행합니다. 각 테스트가 시작되기 전에 를 호출 Promise할 iFrame의 onload이벤트를 resolve()설정하고 iFrame의을 설정 src하고 promise를 반환 하는를 만듭니다.
따라서을 호출 loadUrl(url).then(myFunc)하면 무엇이든지 실행하기 전에 페이지가로드 될 때까지 기다립니다 myFunc.
주로 DOM 변경을 허용하기 위해 (예 : 버튼 클릭을 흉내 내고 div가 숨기고 표시 될 때까지 기다릴 때까지) 내 테스트 (URL로드뿐만 아니라) 전체에서 이런 종류의 패턴을 사용합니다.
이 디자인의 단점은 몇 줄의 코드로 익명 함수를 계속 작성하고 있다는 것입니다. 또한 해결 방법 (QUnit assert.async())이 있지만 약속을 정의하는 테스트 함수는 약속이 실행되기 전에 완료됩니다.
Promise.NET의 .NET과 유사하게 해결 될 때까지 또는 대기 (블록 / 슬립) 에서 값을 가져 오는 방법이 있는지 궁금합니다 IAsyncResult.WaitHandle.WaitOne(). JavaScript가 단일 스레드라는 것을 알고 있지만 이것이 함수가 양보 할 수 없다는 것을 의미하지는 않기를 바랍니다.
본질적으로 올바른 순서로 결과를 뱉어 내기 위해 다음을 얻을 수있는 방법이 있습니까?
function kickOff() {
return new Promise(function(resolve, reject) {
$("#output").append("start");
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
$("#output").append(" middle");
return " end";
});
};
function getResultFrom(promise) {
// todo
return " end";
}
var promise = kickOff();
var result = getResultFrom(promise);
$("#output").append(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
답변
.NET의 IAsyncResult.WaitHandle.WaitOne ()과 유사하게 Promise에서 값을 가져 오거나 해결 될 때까지 대기 (차단 / 절전) 할 수있는 방법이 있는지 궁금합니다. 자바 스크립트가 단일 스레드라는 것을 알고 있지만 이것이 함수가 양보 할 수 없다는 것을 의미하지는 않기를 바랍니다.
브라우저에서 자바 스크립트의 현재 세대는없는 wait()또는 sleep()그 실행에 다른 일을 할 수 있습니다. 그래서 당신은 단순히 당신이 요구하는 것을 할 수 없습니다. 대신, 작업을 수행 한 다음 완료되면 호출하는 비동기 작업이 있습니다 (Promise를 사용했던 것처럼).
이것의 일부는 Javascript의 단일 스레드 성 때문입니다. 단일 스레드가 회전 중이면 해당 회전 스레드가 완료 될 때까지 다른 Javascript를 실행할 수 없습니다. ES6는 yield이와 같은 협력적인 트릭을 허용하는 생성기를 도입 했지만, 설치된 브라우저의 광범위한 견본에서 사용할 수있는 방법은 상당히 많습니다 (JS 엔진을 제어하는 서버 측 개발에서 사용할 수 있습니다) 사용중인).
약속 기반 코드를주의 깊게 관리하면 많은 비동기 작업의 실행 순서를 제어 할 수 있습니다.
코드에서 달성하려는 순서를 정확히 이해하지 못했지만 기존 kickOff()함수를 사용하여 이와 같은 작업을 수행 한 다음 .then()호출 한 후 처리기를 연결할 수 있습니다.
function kickOff() {
return new Promise(function(resolve, reject) {
$("#output").append("start");
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
$("#output").append(" middle");
return " end";
});
}
kickOff().then(function(result) {
// use the result here
$("#output").append(result);
});
다음과 같이 보증 된 순서로 출력을 반환합니다.
start
middle
end
2018 년 업데이트 (이 답변이 작성된 후 3 년) :
당신도 당신의 코드를 transpile 또는 지원 ES7 같은 기능을한다는 환경에서 코드를 실행하는 경우 async와 await, 당신은 지금 사용할 수있는 await코드가 “표시”할 약속의 결과를 기다려야한다. 그것은 여전히 약속을 가지고 발전하고 있습니다. 여전히 모든 Javascript를 차단하지는 않지만 더 친숙한 구문으로 순차적 작업을 작성할 수 있습니다.
ES6 방식 대신 :
someFunc().then(someFunc2).then(result => {
// process result here
}).catch(err => {
// process error here
});
다음과 같이 할 수 있습니다.
// returns a promise
async function wrapperFunc() {
try {
let r1 = await someFunc();
let r2 = await someFunc2(r1);
// now process r2
return someValue; // this will be the resolved value of the returned promise
} catch(e) {
console.log(e);
throw e; // let caller know the promise was rejected with this reason
}
}
wrapperFunc().then(result => {
// got final result
}).catch(err => {
// got error
});
답변
ES2016을 사용하는 경우 사용할 수 있습니다 async및 await과 같은 것을 할 :
(async () => {
const data = await fetch(url)
myFunc(data)
}())
ES2015를 사용하는 경우 Generators 를 사용할 수 있습니다 . 구문이 마음에 들지 않으면 여기에 설명 된 대로 async유틸리티 함수 를 사용하여 추상화 할 수 있습니다 .
ES5를 사용하는 경우 Bluebird 와 같은 라이브러리가 더 많은 제어를 제공하기를 원할 것입니다 .
마지막으로 런타임이 ES2015를 지원하는 경우 이미 실행 순서는 Fetch Injection을 사용하여 병렬 처리로 보존 될 수 있습니다 .
답변
또 다른 옵션은 Promise.all을 사용하여 일련의 프라 미스가 해결 될 때까지 기다리는 것입니다. 아래 코드는 모든 약속이 해결 될 때까지 기다린 다음 모든 준비가 완료되면 결과를 처리하는 방법을 보여줍니다 (질문의 목적인 것처럼 보임). 그러나 start는 resolve를 호출하기 전에 해당 코드를 추가하는 것만으로 middle이 해결되기 전에 분명히 출력 할 수 있습니다.
function kickOff() {
let start = new Promise((resolve, reject) => resolve("start"))
let middle = new Promise((resolve, reject) => {
setTimeout(() => resolve(" middle"), 1000)
})
let end = new Promise((resolve, reject) => resolve(" end"))
Promise.all([start, middle, end]).then(results => {
results.forEach(result => $("#output").append(result))
})
}
kickOff()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
답변
수동으로 할 수 있습니다. (그게 좋은 해결책은 아니지만 ..) 값이 없을 while때까지 루프를 사용하십시오.result
kickOff().then(function(result) {
while(true){
if (result === undefined) continue;
else {
$("#output").append(result);
return;
}
}
});
답변
