복귀를 기다리는 약속과 복귀를 약속하는 약속의 차이
아래 코드 샘플을 고려할 때 동작에 차이가 있습니까? 만약 있다면, 어떤 차이가 있습니까?
return await promise
async function delay1Second() {
return (await delay(1000));
}
return promise
async function delay1Second() {
return delay(1000);
}
제가 알기로는 첫 번째는 비동기 함수 내에서 오류 처리를 하고, 비동기 함수의 Promise에서 오류가 거품처럼 튀어나올 것입니다.그러나 두 번째는 체크 표시가 하나 더 적게 필요합니다.이거 맞는건가요?
이 스니펫은 참조용으로 약속을 반환하는 일반적인 기능입니다.
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
대부분의 경우, 관측 가능한 차이는 없습니다.return
그리고.return await
의 두 버전 모두delay1Second
정확히 동일한 관찰 가능한 동작을 가지고 있습니다(그러나 구현에 따라,return await
의 경우 가 조금 더될 수 .Promise
개체가 생성될 수 있음).
, @가 한 가지 : @PitaJ 지듯이했적가, @PitaJ 차다경하있습, 이가있우가: 니나에약만는만하지▁the▁however만▁if▁where:에약pit다▁@습▁there▁as니있▁out하나,rence:우는가▁there▁@▁diffe.return
또는return await
는 에내됨에 되어 있습니다.try
-catch
이. 이 예를 생각해 보십시오.
async function rejectionWithReturnAwait () {
try {
return await Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
async function rejectionWithReturn () {
try {
return Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
첫 번째 버전에서 비동기 함수는 결과를 반환하기 전에 거부된 약속을 대기하므로 거부가 예외로 전환되고catch
도달할 절. 따라서 함수는 "Saved!" 문자열로 확인하는 약속을 반환합니다.
그러나 두 번째 버전의 함수는 비동기 함수 내에서 거부된 약속을 기다리지 않고 직접 반환합니다. 즉,catch
사례가 호출되지 않고 발신자가 대신 거부를 받습니다.
다른 답변에서 언급했듯이, 약속을 직접 반환함으로써 약속을 부풀릴 때 약간의 성과 이익이 있을 수 있습니다. 단순히 먼저 결과를 기다렸다가 다시 다른 약속으로 마무리할 필요가 없기 때문입니다.하지만 아직 아무도 테일 콜 최적화에 대해 이야기하지 않았습니다.
테일 콜 최적화 또는 "적절한 테일 콜"은 인터프리터가 콜 스택을 최적화하기 위해 사용하는 기술입니다.기술적으로는 ES6 Standard의 일부이지만, 현재는 아직 많은 런타임이 지원하지 않지만, 향후 지원이 추가될 수도 있으므로 현재 좋은 코드를 작성하여 이에 대비할 수 있습니다.
간단히 말해서, TCO(또는 PTC)는 다른 함수에 의해 직접 반환되는 함수에 대해 새 프레임을 열지 않음으로써 통화 스택을 최적화합니다.대신, 동일한 프레임을 재사용합니다.
async function delay1Second() {
return delay(1000);
}
때부터delay()
의 직접반다니됩에서 직접 합니다.delay1Second()
supporting PTC의 .delay1Second()
(외부 함수), 그러나 다른 프레임을 여는 대신delay()
(내부 기능), 외부 기능에 대해 열린 것과 동일한 프레임을 다시 사용합니다.이것은 스택을 최적화합니다. 왜냐하면 스택 오버플로(hehehe)를 방지할 수 있기 때문입니다.fibonacci(5e+25)
본질적으로 그것은 훨씬 빠른 루프가 됩니다.
PTC는 내부 기능이 직접 반환되는 경우에만 활성화됩니다.함수의 결과가 반환되기 전에 변경된 경우, 예를 들어 반환된 경우에는 사용되지 않습니다.return (delay(1000) || null)
또는return await delay(1000)
.
하지만 앞서 말했듯이 대부분의 런타임과 브라우저는 아직 PTC를 지원하지 않기 때문에 지금은 큰 차이가 없을 수도 있지만 미래에 코드를 보호하는 데는 큰 문제가 되지 않습니다.
이 질문에서 자세히 알아보기:Node.js: 비동기 함수에서 테일 콜에 대한 최적화가 있습니까?
눈에 띄는 차이: 약속 거부는 다른 위치에서 처리됩니다.
return somePromise
상담 사이트에 약속을 전달할 것입니다.await
콜 사이트에서 해결하기로 약속합니다(있는 경우).따라서 일부 약속이 거부되면 로컬 캐치 블록이 아닌 콜 사이트의 캐치 블록에서 처리됩니다.
async function foo () {
try {
return Promise.reject();
} catch (e) {
console.log('IN');
}
}
(async function main () {
try {
let a = await foo();
} catch (e) {
console.log('OUT');
}
})();
// 'OUT'
return await somePromise
먼저 현지에서 정착하기 위한 약속을 기다릴 것입니다.따라서 값 또는 예외가 먼저 로컬에서 처리됩니다.=> 로컬 캐치 블록은 다음과 같은 경우에 실행됩니다.somePromise
거부되었습니다.
async function foo () {
try {
return await Promise.reject();
} catch (e) {
console.log('IN');
}
}
(async function main () {
try {
let a = await foo();
} catch (e) {
console.log('OUT');
}
})();
// 'IN'
이유:return await Promise
모두에서 기다리고 .return Promise
밖에서만 기다리는
세부 단계:
반환 약속
async function delay1Second() {
return delay(1000);
}
- 을 부르다
delay1Second()
;
const result = await delay1Second();
- 에 안에.
delay1Second()
, 함수입니다.delay(1000)
을 즉을시반으로 합니다.[[PromiseStatus]]: 'pending
끝내꾸나라고 부르자.delayPromise
.
async function delay1Second() {
return delayPromise;
// delayPromise.[[PromiseStatus]]: 'pending'
// delayPromise.[[PromiseValue]]: undefined
}
- 을 비기함반값내감쌉니다부로을동환수 안으로 감쌀 입니다.
Promise.resolve()
(출처).왜냐면delay1Second
비동기 함수로, 다음과 같은 기능이 있습니다.
const result = await Promise.resolve(delayPromise);
// delayPromise.[[PromiseStatus]]: 'pending'
// delayPromise.[[PromiseValue]]: undefined
Promise.resolve(delayPromise)
아온다를 합니다.delayPromise
입력이 이미 약속이기 때문에 아무것도 수행하지 않고(MDN Promise.resolve 참조):
const result = await delayPromise;
// delayPromise.[[PromiseStatus]]: 'pending'
// delayPromise.[[PromiseValue]]: undefined
await
다음 시간까지 기다립니다.delayPromise
해결되었습니다.
- 한다면
delayPromise
PromiseValue=1:
const result = 1;
- 는 ELSE »
delayPromise
거부됨:
// jump to catch block if there is any
약속을 기다리며 돌아오세요.
async function delay1Second() {
return await delay(1000);
}
- 을 부르다
delay1Second()
;
const result = await delay1Second();
- 에 안에.
delay1Second()
, 함수입니다.delay(1000)
을 즉을시반으로 합니다.[[PromiseStatus]]: 'pending
끝내꾸나라고 부르자.delayPromise
.
async function delay1Second() {
return await delayPromise;
// delayPromise.[[PromiseStatus]]: 'pending'
// delayPromise.[[PromiseValue]]: undefined
}
- 로컬 대기는 다음 시간까지 대기합니다.
delayPromise
자리를 잡습니다.
- 사례 1:
delayPromise
PromiseValue=1:
async function delay1Second() {
return 1;
}
const result = await Promise.resolve(1); // let's call it "newPromise"
const result = await newPromise;
// newPromise.[[PromiseStatus]]: 'resolved'
// newPromise.[[PromiseValue]]: 1
const result = 1;
- 사례 2:
delayPromise
거부됨:
// jump to catch block inside `delay1Second` if there is any
// let's say a value -1 is returned in the end
const result = await Promise.resolve(-1); // call it newPromise
const result = await newPromise;
// newPromise.[[PromiseStatus]]: 'resolved'
// newPromise.[[PromiseValue]]: -1
const result = -1;
용어집:
- 정착:
Promise.[[PromiseStatus]]
에서 변경된pending
resolved
또는rejected
대답하기 입니다. (아마도 어질문니다입려운대기하답이은것prob▁your다니▁this▁to질입▁(pil▁trans문ably)에 달려있기 때문입니다. 왜냐하면 실제로는 트랜스파일러가 어떻게 작동하는지에 달려있기 때문입니다(아마도).babel
렌더링합니다.async/await
이와 관계없이 명확한 것은 다음과 같습니다.
두 구현 모두 동일하게 동작해야 합니다. 첫 구현은 하나만 더 적을 수 있습니다.
Promise
특히 당신이 불필요한 것들을 떨어뜨린다면.
await
두 번째 버전은 트랜스파일러의 추가 코드를 요구하지 않지만 첫 번째 버전은 요구합니다.
따라서 코드 성능 및 디버깅 관점에서 볼 때, 두 번째 버전이 더 바람직하지만, 두 번째 버전은 약간의 가독성 이점이 있는 반면 첫 번째 버전은 약속을 반환한다는 것을 명확하게 나타냅니다.
저희 프로젝트에서는 항상 'return wait'을 사용하기로 했습니다.그 주장은 "나중에 트라이캐치 블록에 반환 표현 주위에 놓였을 때 '대기'를 추가하는 것을 잊어버릴 위험이 지금 중복된 '대기'를 갖는 것을 정당화한다"는 것입니다.
다음은 실행하여 "반환 대기"가 필요하다고 확신할 수 있는 유형의 스크립트 예제입니다.
async function test() {
try {
return await throwErr(); // this is correct
// return throwErr(); // this will prevent inner catch to ever to be reached
}
catch (err) {
console.log("inner catch is reached")
return
}
}
const throwErr = async () => {
throw("Fake error")
}
void test().then(() => {
console.log("done")
}).catch(e => {
console.log("outer catch is reached")
});
여기서 나는 당신이 이해할 수 있도록 실용적인 코드를 남깁니다.
let x = async function () {
return new Promise((res, rej) => {
setTimeout(async function () {
console.log("finished 1");
return await new Promise((resolve, reject) => { // delete the return and you will see the difference
setTimeout(function () {
resolve("woo2");
console.log("finished 2");
}, 5000);
});
res("woo1");
}, 3000);
});
};
(async function () {
var counter = 0;
const a = setInterval(function () { // counter for every second, this is just to see the precision and understand the code
if (counter == 7) {
clearInterval(a);
}
console.log(counter);
counter = counter + 1;
}, 1000);
console.time("time1");
console.log("hello i starting first of all");
await x();
console.log("more code...");
console.timeEnd("time1");
})();
함수 "x"는 "more code..."를 출력하는 반환을 삭제할 경우 다른 함수보다 함수 비동기입니다.
변수 x는 단지 비동기 함수일 뿐이며, 코드의 메인에서 변수 x의 함수를 호출하기 위해 대기를 호출하고, 완료되면 "sysc / wait"에 대해 정상적인 코드 순서를 따르지만, x 함수 내부에는 다른 비동기 함수가 있고, 이것은약속을 반환하거나 "x 함수 안에 머물며 주 코드를 잊어버리므로" console.log를 인쇄하지 않습니다."("more code .")라는 약속을 반환합니다.반면에, "), 만약 우리가 "를 넣는다면, 그것은 "그것은 메인 코드의 정상적인 순서를 따르고 완료되는 모든 함수를 기다릴 것입니다.
"delete the" return" (1 "delete the" return") 아래에 있는 동작을 볼 수 있습니다.
언급URL : https://stackoverflow.com/questions/38708550/difference-between-return-await-promise-and-return-promise
'programing' 카테고리의 다른 글
Oracle에서 변수 값을 선택하는 방법은 무엇입니까? (0) | 2023.07.28 |
---|---|
c에서 함수에 대한 인수로 수신된 정수 배열의 크기 찾기 (0) | 2023.07.23 |
JavaScript 파일에 매개 변수 전달 (0) | 2023.07.23 |
Python 2.7은 사용자 입력을 받고 인용문 없이 문자열로 조작합니다. (0) | 2023.07.23 |
각 연결된 항목의 개수와 함께 group_concat을 사용하는 SQL이 아니라 한 행의 총 개수입니다. (0) | 2023.07.23 |