Javascript에서 비동기 및 약속과 관련된 몇 가지 실수

13673 단어 webdevjavascript
안녕하세요, 오늘 저는 Javascript Promise, Async-await 및 제가 작업할 때 저질렀던 몇 가지 실수에 대해 이야기할 것입니다.

새로운 실수를 발견할 때마다 이 게시물을 업데이트하기 위해 다시 돌아오겠습니다.

1. 콘솔을 완전히 신뢰하지 마십시오.*(..)



음, 오늘 우리의 주제와 관련이 없을 수도 있지만 실제로는 그렇습니다. 이것은 거의 발생하지 않을 수 있습니다(실제로 지난 2년 동안, 나는 그것을 여러 번 접했습니다).

console.*은 표준화되지 않았으며 console.* 메서드의 작동 방식을 보여주는 사양이나 규칙이 없습니다. 따라서 console.*의 동작을 확실히 알 수 없습니다. 그들의 결과는 때때로 변경될 수 있으며, 내가 보여주려는 예제의 결과는 이 블로그를 읽을 때 브라우저에 표시되는 결과와 동일하지 않을 수 있습니다. 우리는 결코 모른다.

매우 간단한 예를 살펴보겠습니다.

const a = {
    value: 10,
};
console.log(`a`, a);
a.value = 20;


여러분이 기대하는 것은 다음과 같습니다.

{value: 10}


실제로 그렇습니다. 하지만 언젠가는 다음과 같이 기록될 것임을 지적하고 싶습니다.

{value: 20}


여러분에게 보여주기 위해 사례를 재현하는 것은 어렵지만 실제로 일어날 수 있습니다. 아마도 매우 큰 프로젝트를 실행하고 코드를 빠르게 변경하면 console.*은 여러분이 결코 알지 못하는 이상한 동작을 할 것입니다.

위의 시나리오를 실행하는 경우 할 수 있는 최선의 옵션은 대신 디버거를 사용하거나 JSON.stringify를 사용하여 변수의 "스냅샷"을 만드는 것입니다(객체 유형에 대해 이야기하고 있음).

2. 해결/거절은 "반품"과 동일하지 않습니다.



개발 중에 한 가지 실수는 resolve/reject가 Promise의 "return"키워드라고 가정한 것입니다. 기술적으로는 사실이지만 한 가지 주의할 점은 해결/거절을 호출하더라도 Promise는 해당 지점에서 멈추지 않고 Promise가 끝날 때까지 실행된다는 것입니다.

이 예를 보자:

const a = new Promise((resolve) => {
    resolve(1);
    console.log("still go here");
});

a.then((res) => {
    console.log(res);
});

// Result
still go here
1


그리고

const a = new Promise((resolve, reject) => {
    reject(2);
    console.log("still go here");
});

a.then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err);
});
// Result
still go here
2


console.log 이전에 resolve/reject를 호출했지만 여전히 화면에 출력됩니다. 즉, Promise는 여전히 해당 줄로 이동하여 resolve/reject가 호출된 후에도 코드를 실행합니다.

"return"을 호출하면 해당 지점에서 함수가 중지되는 함수와 다릅니다(조건부 반환에 대해 말하는 것이 아닙니다).

예전에 해결/거절을 "반환"으로 가정했기 때문에 수정하는 데 2일이 걸리는 버그를 만들었기 때문에 이것을 여러분과 공유하고 싶습니다!

3. 첫 번째가 선택됩니다



Promise에서 resolve/reject를 여러 번 호출할 수 있지만 첫 번째 호출만 수락되고 Promise의 출력이 됩니다. 물론 정상적인 흐름을 말하는 거고, 조건부 흐름이라면 이야기가 달라지겠죠.

const a = new Promise((resolve) => {
    resolve(1);
    resolve(2);
});

a.then(console.log);

// Output: 
1



const a = new Promise((resolve, reject) => {
    reject(2);
    reject(1);
});

a.catch(console.log);
**// Output
2**


resolve/reject에 전달하는 매개변수에서도 같은 일이 발생합니다. 여러 매개변수로 resolve/reject를 호출할 수 있지만 첫 번째 매개변수만 resolve/reject의 값으로 선택되고 첫 번째 매개변수 이후의 모든 후속 매개변수는 침묵 무시.

const a = new Promise((resolve, reject) => {
    resolve(1, 2, 3);
});

a.then(console.log);

// Ouput
1


1개 이상의 값을 반환하고 싶다면 객체나 배열에 넣을 수밖에 없습니다.

const a = new Promise((resolve, reject) => {
    resolve([1, 2, 3]);
});

a.then(console.log);

// Ouput
[1,2,3]


4. 불필요한 대기 반환.



좋아요, 좀 더 명확하게 할게요.

아래 예를 고려하십시오

const promise = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("done");
        }, 1500);
    });

const makeRequest = async () => {
    return await promise();
};

const test = async () => {
    const result = await makeRequest();
    console.log(result);
};

test();

// result
// after 1.5s, print out "done"


return await promise() 에 대한 알림입니다. 저 뿐만 아니라 많은 초보자들이 가끔 그런 코드를 작성하는 것 같아요. 틀린 말은 아니지만 나한테는 좀 쓸데없는 짓이야. make 요청이 서버에 대한 비동기 요청을 만들고 다른 약속을 반환할 수 있기 때문입니다. 데이터로 아무 것도 처리할 필요가 없지만 즉시 반환하는 경우 반환하기 전에 응답을 기다릴 필요가 없습니다.

이 코드도 위와 동일하게 작동합니다.

const promise = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("done");
        }, 1500);
    });

const makeRequest = async () => {
    return promise();
};

const test = async () => {
    const result = await makeRequest();
    console.log(result);
};

test();

// Result
// after 1.5s, print out "done"


자, 오늘은 여기까지입니다. 다음에 만나요. 안녕

좋은 웹페이지 즐겨찾기