Skip to main content
편집기를 닫는 일은 session.close() 한 줄이면 됩니다. 문제는 언제 닫느냐입니다. 저장 결과를 내 서버에 반영하고 계신다면 그 작업이 끝나기 전에 닫으면 반영이 유실됩니다.

무엇이 문제인가

사용자가 편집기 안에서 나가기나 장바구니 이동을 누르면 편집기는 메시지를 두 번 보냅니다.
  1. save-doc-report (status: 'end')
  2. close 또는 goto-cart
호스트가 1번 핸들러에서 썸네일이나 docInfo를 자기 서버에 반영한다면, 그것은 네트워크 호출이라 2번이 도착한 시점에 아직 진행 중일 수 있습니다. 이벤트 핸들러 안의 await는 다음 이벤트의 처리를 막아 주지 않습니다. 그래서 아래 코드는 틀렸습니다.

waitForExit()

세션은 핸들러가 반환한 Promise를 추적합니다. waitForExit()는 종료 요청이 도착한 시점에 진행 중이던 핸들러 Promise가 전부 settle된 뒤에 resolve합니다.
핸들러가 async여서 Promise를 반환하기만 하면 됩니다. 따로 등록할 것이 없습니다.

동작 규칙

1

스냅샷

종료 요청이 도착한 순간에 진행 중이던 Promise만 기다립니다. 정확히는 그 메시지의 핸들러까지 실행된 직후를 기준으로 삼습니다. 그 뒤에 시작된 작업은 기다리지 않습니다.
2

에러 내성

추적 중인 핸들러가 reject되어도 종료를 막지 않습니다(Promise.allSettled). 그 reject는 세션이 소비하고 console.error로 남기므로 조용히 사라지지는 않습니다. 사용자 안내 같은 실제 에러 처리는 핸들러 안에서 하세요.
3

타임아웃

settleTimeoutMs(기본 10000ms)를 넘기면 console.warn을 남기고 그대로 resolve합니다. 사용자가 편집기에 갇히는 것보다 뒤처리 유실이 낫다는 판단입니다. 무제한으로 기다리려면 Infinity, 아예 기다리지 않으려면 0을 주세요.
4

세션이 먼저 닫히면

waitFor와 마찬가지로 reject합니다.
waitForExit()는 iframe을 제거하지 않습니다. 종료 시점을 알려줄 뿐이고, 실제 정리는 session.close()로 하셔야 합니다.

어떤 이벤트를 기다리나

resolve되는 값이 그 action 이름입니다. 장바구니로 보낼지 원래 화면으로 돌아갈지 이 값으로 분기하시면 됩니다.

no_update를 쓸 때

띄우기 옵션에 no_update: true를 주면 저장 버튼이 나가기로 바뀝니다. 누르면 저장하지 않고 바로 goto-cart를 보냅니다. 이 경우 save-doc-report가 오지 않으므로 저장 후처리도 없습니다.

핸들러 안에서 닫을 때 주의

dispatch는 on과 once 핸들러를 먼저 실행하고 그다음 onAny를 실행합니다. on('goto-cart') 안에서 close()를 부르면 그 자리에서 모든 핸들러가 해제되므로 같은 메시지에 대한 onAny가 실행되지 않습니다. waitForExit()를 쓰면 이 문제도 함께 해결됩니다.

다음 단계

주문

편집이 끝난 프로젝트를 주문으로 넘깁니다.

편집기 이벤트

save-doc-report의 docInfo 전체 필드를 봅니다.