왜 거부가 약속 체인을 통과하지 못하는지 이해할 수 없습니다. 누군가가 이유를 이해하도록 도와주셨으면 좋겠습니다. 나에게 있어 일련의 Promise에 기능을 추가한다는 것은 원래 Promise의 의도를 이행한다는 의미입니다. 이것은 설명하기 어렵기 때문에 먼저 내 문제의 코드 예제를 보여 드리겠습니다. (참고: 이 예에서는 Node와 지연된 노드 모듈을 사용합니다. Dojo 1.8.3을 사용하여 테스트했는데 동일한 결과를 얻었습니다.)
으아악이를 실행한 결과는 다음과 같습니다.
으아악글쎄, 나에게는 이 결과가 말이 안 된다. 이 Promise 체인에 추가함으로써 각각은 d1의 성공적인 해결과 체인을 따라 전달되는 결과에 의존한다는 의도를 암시합니다. promise1의 Promise가 Wins 값을 받지 못하고 오류 처리기의 err 값을 받은 경우 체인의 다음 Promise가 어떻게 성공 함수를 호출할 수 있나요? 값 자체를 가져오지 않기 때문에 다음 Promise에 의미 있는 값을 전달할 수 없습니다.
내 아이디어를 다른 방식으로 설명할 수 있습니다. John, Ginger, Bob 세 사람이 있습니다. John은 위젯 상점을 소유하고 있습니다. Ginger는 가게에 들어와서 다양한 색상의 위젯이 담긴 가방을 달라고 했습니다. 그는 재고가 없었기 때문에 딜러에게 배송을 요청했습니다. 그 사이에 그는 Ginger에게 위젯 가방을 빚졌다며 우천 수표를 줍니다. Bob은 Ginger가 위젯을 가져오는 것을 발견하고 작업이 끝나면 파란색 위젯을 가져오라고 요청합니다. 그녀는 동의했고 그에게 동의하겠다고 메모를 보냈습니다. 이제 John의 딜러는 공급품에서 어떤 위젯도 찾을 수 없으며 제조업체는 더 이상 위젯을 만들지 않습니다. 그래서 John에게 알립니다. John은 차례로 Ginger에게 위젯을 얻을 수 없다고 알립니다. Bob이 직접 아무것도 얻지 못했는데 어떻게 Ginger로부터 파란색 위젯을 얻을 수 있습니까?
이 문제에 대한 나의 세 번째, 보다 현실적인 관점은 이것이다. 데이터베이스에 업데이트하려는 두 개의 값이 있다고 가정해 보겠습니다. 하나는 다른 하나의 ID에 따라 다르지만 데이터베이스에 삽입하고 결과를 얻을 때까지 ID를 얻을 수 없습니다. 게다가 첫 번째 삽입은 데이터베이스 쿼리에 따라 달라집니다. 데이터베이스 호출에서 반환된 Promise는 두 호출을 시퀀스로 연결하는 데 사용됩니다.
으아악이제 이 경우 db.query가 실패하면 먼저 그 다음의 err 함수를 호출합니다. 그러나 다음 Promise의 성공 함수를 호출합니다. 이 Promise는 첫 번째 값의 결과를 기대하지만 오류 처리 기능에서 오류 메시지를 받습니다.
그래서 제 질문은, 성공 함수에서 오류를 테스트해야 하는데 왜 오류 처리 기능이 있는 걸까요?
죄송합니다. 게시물이 너무 깁니다. 다른 방법으로 설명하는 방법을 모르겠습니다.
업데이트 및 수정
(참고: 일부 댓글에 달았던 답글을 삭제했습니다. 따라서 누군가가 내 답글에 댓글을 달면 그 댓글이 맥락에 맞지 않게 나타날 수 있습니다. 죄송합니다. 최대한 짧게 유지하려고 노력하고 있습니다. 가능해요 )
답변해주신 모든 분들께 감사드립니다. 먼저 내 질문이 얼마나 형편없이 작성되었는지, 특히 내 의사코드에 대해 모든 사람에게 사과하고 싶습니다. 나는 그것을 짧게 유지하려고 노력하는 데 조금 너무 공격적이었습니다.
Bergi 답변 감사드립니다. 제 논리에 오류가 있는 것 같습니다. 내가 겪고 있는 문제를 일으키는 또 다른 문제를 간과하고 있는 것 같습니다. 이로 인해 약속 체인이 내가 상상했던 것과 다르게 작동할 수 있습니다. 나는 여전히 코드의 다양한 요소를 테스트하고 있기 때문에 내가 뭘 잘못하고 있는지 확인하기 위한 적절한 질문을 공식화할 수도 없습니다. 하지만 저는 모든 사람에게 상황을 업데이트하고 싶었고 도움을 주셔서 감사드립니다.
P粉1557104252023-10-24 16:07:16
@Jordan 우선, 댓글 작성자가 지적했듯이 첫 번째 예제는 게으른 라이브러리를 사용할 때 기대하는 결과를 확실히 생성할 것입니다.
으아악둘째, 제안한 출력이 생성되더라도 두 번째 코드 조각의 실행 흐름에는 영향을 미치지 않습니다. 이는 약간 다르며 다음과 같습니다.
으아악첫 번째 약속이 거부되면 다음만 출력됩니다.
으아악그러나 (재미있는 부분에 도달) 심지어 지연된 라이브러리도 확실히 반환됩니다 3 x returned
,大多数其他承诺库将返回 1 x returned, 2 x 已解决
(이는 다른 Promise 라이브러리를 사용하여 이러한 결과를 얻는다는 가정으로 이어집니다).
또한 혼란스러운 점은 다른 라이브러리가 더 올바르게 작동한다는 것입니다. 설명하겠습니다.
동기 세계에서 "약속 거부"에 대응하는 것은 抛出
。因此从语义上讲,同步中的异步 deferred.reject(new Error())
等于 throw new Error()
입니다.
귀하의 예에서는 동기 콜백에 오류가 발생하지 않고 단지 반환만 하므로 오류가 성공 값인 성공 흐름으로 전환합니다. 거부가 더 진행되도록 하려면 오류를 다시 발생시켜야 합니다:
이제 질문은 지연 라이브러리가 반환된 오류를 거부로 처리하는 이유입니다.
이유는 지연된 작업에 대한 거부감이 조금 다르기 때문입니다. deferred lib에서 규칙은 다음과 같습니다. 오류 인스턴스가 발생하면 약속이 거부됩니다. 따라서 deferred.resolve(new Error())
它也会起作用如 deferred.reject(new Error()) ,如果你尝试执行 deferred.reject(notAnError) ,它会抛出一个异常,表示该 Promise 只能被拒绝有错误的实例。这清楚地表明了为什么从 then
콜백을 실행하더라도 반환된 오류는 약속을 거부합니다.
defer 논리 뒤에는 몇 가지 타당한 추론이 있지만 여전히 JavaScript에서 작동하는 방식throw
과 일치하지 않으므로 이 동작은 지연된 v0.7 릴리스에서 변경될 예정입니다.
간단한 요약:
혼란과 예상치 못한 결과를 피하려면 모범 사례의 규칙을 따르세요.
위 사항을 준수하면 지연된 라이브러리 및 기타 인기 있는 Promise 라이브러리에서 일관되고 예상되는 결과를 얻을 수 있습니다.
P粉3767388752023-10-24 12:09:36
아니요. 당신이 설명하는 것은 체인이 아니라 모든 콜백을 처리하는 d1
。然而,如果您想使用 then
链接某些内容,promise2
的结果取决于 promise1
的分辨率以及 promise1
的分辨率以及 < code>然后콜백에 추가하는 것입니다.
문서에는 다음과 같이 명시되어 있습니다.
.then
方法通常根据 Promises 来看待/A 规范(或者更严格的Promsises/A+ )。这意味着回调 shell 返回的 Promise 将被同化为 Promise2 的解析,如果没有成功/错误处理程序,相应的结果将直接传递给 Promise2 코드> - 간단히 핸들러를 생략하여 오류를 전파할 수 있습니다.
그러나 오류가 handled인 경우 결과 promise2
는 수정된 것으로 간주되어 해당 값으로 이행됩니다. 이런 일이 발생하지 않도록 하려면 try-catch 절에서와 마찬가지로 오류를 promise2
被视为已修复,并将用该值来实现。如果您不希望出现这种情况,则必须重新抛出
다시 발생해야 합니다 . 또는 핸들러에서 (보류 중인) 거부된 Promise를 반환할 수 있습니다. Dojo의 거부가 무엇인지는 잘 모르겠지만,
그 사람은 그러면 안 돼요. 오류 핸들러가 없으면 그는 ((John이) Ginger로부터) 위젯이 남아 있지 않다는 메시지만 인식할 것입니다. 그러나 Ginger가 이 상황에 대해 오류 핸들러를 설정하면 John 또는 그의 딜러가 파란색 위젯이 남지 않은 경우 그녀는 Bob에게 자신의 오두막에 있는 녹색 위젯을 주겠다는 약속을 여전히 이행할 수 있습니다
.오류 콜백을 메타로 변환하려면 "위젯이 남아 있지 않으면 그에게 위젯이 남아 있지 않다는 코멘트를 주십시오. 이는 필수 위젯과 동일합니다."와 같은 오류를 핸들러에서 반환합니다.
...이는 오류가 그곳에서 처리되었음을 의미합니다. 그렇지 않은 경우에는 오류 콜백을 생략하세요. 그런데, 당신의 성공 콜백은 그들이 만드는 약속을 返回
아니기 때문에 쓸모없어 보입니다. 올바른 것은:
또는 이전 콜백의 결과 값에 액세스하기 위해 클로저가 필요하지 않으므로 다음과 같이 해도 됩니다.
으아아아