안녕 try/catch hello 오류 반환
23419 단어 gojavascripttypescripterrors
문제: Typescript와 javascript는 함수가 오류를 발생시킬 수 있음을 나타낼 방법이 없습니다. 따라서 일반적으로 충돌이 발생할 때까지 코드를 실행하거나 github 또는 node_modules에서 소스 코드를 추적하여(번들된 dist에는 일반적으로 축소되지 않은 헤더만 있기 때문에) 시도/잡을 위치를 파악해야 합니다.
오류 반환 패턴은 도구가 오류가 발생할 수 있는 위치를 추적하므로 해당 정보를 직접 암기하거나 찾을 필요가 없습니다. 오류 반환을 사용하면 처리되지 않은 오류가 타이프 스크립트 오류와 함께 편집기에 즉시 표시됩니다.
다음은 순차적인 분기 네트워킹 작업의 패턴 예입니다.
async function loadSong(id: string): Err | Song {
const metadata = await loadMetadata(id)
if (isErr(metadata)) return metadata // returns error!
const mp3 = await loadMp3(id)
if (!isErr(mp3)) return Song(metadata, mp3)
// try ogg it might work
const ogg = await loadOgg(id)
if (!isErr(ogg)) return Song(metadata, ogg)
// maybe the mirror has it?
const mirrorMp3 = await loadMp3(id, { useMirror: true })
if (!isErr(mirrorMp3)) return Song(metadata, mirrorMp3)
return Err('all audio hosts failed')
}
(try-catch를 사용한 4단계 들여쓰기와 비교하면 꽤 좋습니다.)
그런 다음, 예를 들어 html 요소에서 오류를 포착하지 않고 이 함수를 사용하려고 하면 유형 오류가 발생합니다.
const addElm = document.body.appendChild
function playSong(id: string) {
const song = loadSong(id)
addElm(Player(song).play())
// ↑ typescript error: .play() does not exist on type Err
addElm(Metadata(song))
// ↑ same error
}
패턴은 실패 사례를 설명하도록 강제합니다.
// Good code: won't runtime error and has no typescript errors
function playSong(id: string) {
const song = loadSong(id)
if (isErr(song)) {
addElm(ErrorDiv('could not load song'))
return
}
addElm(Player(song).play())
addElm(Metadata(song))
}
다음을 방지하는 데 유용합니다.
당신은 라이브러리가 필요하지 않습니다
이 패턴에 대한 모든 코드는 짧은 파일에 적합하며 필요에 따라 사용자 지정할 수 있습니다. 내 구현은 다음과 같습니다.
// err.ts:
const ERR = Symbol('ERR')
type Err = {
[ERR]: true
error: unknown
type?: ErrTypes
}
/** Optional addition if you want to handle errors differently based on their type */
type ErrTypes = 'internet' | 'fileSystem' | 'badInput'
export function isErr(x: unknown): x is Err {
return typeof x === 'object' && x != null && ERR in x
}
export function Err(message: string, type?: string) {
return { [ERR]: true, error: message, type: type }
}
/** Make an error-throwing function into a error-returning function */
export async function tryFail<T>(
f: (() => Promise<T>) | (() => T)
): Promise<T | Err> {
try {
return await f()
} catch (e) {
return { [ERR]: true, error: e }
}
}
/** If you need to convert your error values back into throw/catch land */
export function assertOk<T>(x: T | Err) {
if (isErr(x)) throw Error(x.error)
}
가져오기 없이 항상 사용할 수 있도록 전역 패키지 범위에 넣는 것이 좋습니다.
외부 라이브러리 및 stdlib에 오류 반환 패턴 사용
예를 들어 설명하기 가장 쉬움
/** Sometimes has error in runtime and crashes server */
function getUserBad1(id: string) {
const buf = readFileSync(`./users/${id}.json`)
return JSON.parse(buf.toString())
}
/** Works but verbose: */
function getUserBad2(id: string) {
let buf: Buffer
try {
buf = readFileSync(`./users/${id}.json`)
} catch (e) {
console.warn('could not read file:', e)
return null
}
let user: User
try {
user = JSON.parse(buf.toString())
return user
} catch (e) {
console.warn('could not parse user file as json')
return null
}
}
/** tryFail pattern is best of both worlds */
function getUser(id: string) {
const buf = tryFail(() => readFileSync(`./users/${id}.json`))
if (isErr(buf)) return buf
return tryFail(() => JSON.parse(buf.toString()))
}
오류를 반환하도록 신뢰할 수 없는 함수를 래핑합니다.
모든 곳에서 일부 라이브러리 함수를 사용 중이고 모든 곳에서
tryFail(()=>...)
를 반복하는 데 지쳤다면(대량의 try-catch 체인을 이기는 경우에도) 오류 반환 논리로 라이브러리를 래핑하는 것이 도움이 될 수 있습니다.오류 라이브러리에 함수가 하나만 더 필요합니다.
// err.ts:
function errReturnify<In, Out>(
f: (...args: In) => Out
): (...args: In) => Out | Err {
return (...args: In) => {
try {
return f()
} catch (e) {
if (e instanceof Error) return Err(e.message)
return Err(`unknown error in ${f.name}: ${JSON.stringify(e)}`)
}
}
}
그런 다음 이를 사용하여 래핑된 라이브러리를 만들 수 있습니다.
// wrapped/fs.ts
/** Wrap up error-throwing functions into error-returning ones */
import {
cpSync as cpSync_,
mkdirSync as mkdirSync_,
readFileSync as readFileSync_,
} from 'fs'
export const cpSync = errReturnify(cpSync_)
export const mkdirSync = errReturnify(mkdirSync_)
export const readFileSync = errReturnify(readFileSync_)
// wrapped/JSON.ts
export default JSON = {
parse: errReturnify(JSON.parse),
stringify: JSON.stringify,
}
그러면 완벽한 우아함과 신뢰성으로 라이브러리 코드를 사용할 수 있습니다.
// server.ts
import { readFileSync } from './wrapped/fs'
import JSON from './wrapped/JSON'
function getUser(id: string) {
const buf = readFileSync(`./users/${id}.json`)
if (isErr(buf)) return buf
return JSON.parse(buf.toString())
}
약간의 불편함은 있지만 아무 함수나 래핑하는 데 두 줄이면 됩니다
f
. f
를 몇 번 이상 사용한다면 노력할 가치가 있습니다.결론
요컨대, 이 간단한 패턴은 TypeScript 네트워킹 코드에 널리 퍼져 있는 중첩된 try/catch가 있는 어색한 비어 있음
let
을 피하면서 TypeScript 코드를 훨씬 더 안정적으로 만들 수 있습니다.
Reference
이 문제에 관하여(안녕 try/catch hello 오류 반환), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/qpwo/goodbye-trycatch-hello-error-return-5hcp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)