
프로그램에 실패를 인코딩합니다.
이 패키지에는 성공 ( Ok ) 또는 실패 ( Err )를 나타내는 Result 유형이 포함되어 있습니다.
비동기 작업의 경우 neverthrow Promise<Result<T, E>> 래핑하는 ResultAsync 클래스를 제공하고 정기적 인 Result<T, E> 와 동일한 수준의 표현성과 제어를 제공합니다.
ResultAsync thenable 의미는 아마도 기본 Promise<Result> 와 똑같이 행동한다는 Result .then await 예제 및 모범 사례는 위키에 확인하십시오.
오류 처리를 위해이 패키지를 활용하는 방법에 대한 실제 사례를 볼 필요가 있습니까? 이 repo : https://github.com/parlez-vous/server를 참조하십시오
eslint-plugin-neverthrow 사용하십시오Result )okerrResult.isOk (방법)Result.isErr (방법)Result.map (메소드)Result.mapErr (방법)Result.unwrapOr (메소드)Result.andThen .Result.asyncAndThen (메소드)Result.orElse (방법)Result.match (메소드)Result.asyncMap (메소드)Result.andTee (방법)Result.andThrough (메소드)Result.asyncAndThrough (메소드)Result.fromThrowableResult.combine (정적 클래스 방법)Result.combineWithAllErrors (정적 클래스 메소드)Result.safeUnwrap()ResultAsync )okAsyncerrAsyncResultAsync.fromThrowable (정적 클래스 메소드)ResultAsync.fromPromise (정적 클래스 메소드)ResultAsync.fromSafePromise (정적 클래스 메소드)ResultAsync.map (메소드)ResultAsync.mapErr (메소드)ResultAsync.unwrapOr (메소드)ResultAsync.andThen (메소드)ResultAsync.orElse (메소드)ResultAsync.match (메소드)ResultAsync.andTee (메소드)ResultAsync.andThrough (메소드)ResultAsync.combine (정적 클래스 방법)ResultAsync.combineWithAllErrors (정적 클래스 메소드)ResultAsync.safeUnwrap()fromThrowablefromAsyncThrowablefromPromisefromSafePromisesafeTry > npm install neverthroweslint-plugin-neverthrow 사용하십시오 neverthrow S Bounty 프로그램의 일환으로 사용자 MDBetancourt는 eslint-plugin-neverthrow 만들어 오류가 처리되지 않도록했습니다.
실행에 의해 설치 :
> npm install eslint-plugin-neverthrow eslint-plugin-neverthrow 사용하면 다음 세 가지 방법 중 하나에서 결과를 소비해야합니다.
.match 를 호출하십시오.unwrapOr 를 호출합니다._unsafeUnwrap 을 호출합니다 이를 통해 Result 의 오류를 명시 적으로 처리하고 있습니다.
이 플러그인은 본질적으로 Rust의 must-use 속성 포팅입니다.
neverthrow 다음을 노출시킵니다.
ok 편의 기능 Ok 변형 Result 를 생성하는 편의 기능err 편의 기능 Result 의 Err variant를 생성하기 위해Ok 클래스 및 유형Err 와 유형Result 유형 및 Result.fromThrowable 에서 호출 할 수있는 네임 스페이스 / 객체.ResultAsync 클래스okAsync 편의성 기능 Ok 유형 Result 포함하는 결과를 생성하기위한 ResultAsyncerrAsync 편의 함수 Err 유형 Result 포함하는 ResultAsync 생성합니다. import {
ok ,
Ok ,
err ,
Err ,
Result ,
okAsync ,
errAsync ,
ResultAsync ,
fromAsyncThrowable ,
fromThrowable ,
fromPromise ,
fromSafePromise ,
safeTry ,
} from 'neverthrow' neverthrow 최대한 활용하는 방법에 대한 도움은 위키를 확인하십시오.
이 패키지가 유용하다고 생각되면 저를 후원하거나 단순히 커피를 사는 것을 고려하십시오!
Result ) ok Result 의 Ok 변형을 구성합니다
서명:
ok < T , E > ( value : T ) : Ok < T , E > { ... }예:
import { ok } from 'neverthrow'
const myResult = ok ( { myData : 'test' } ) // instance of `Ok`
myResult . isOk ( ) // true
myResult . isErr ( ) // falseback 위로 돌아갑니다
err Result 의 Err 변형을 구성합니다
서명:
err < T , E > ( error : E ) : Err < T , E > { ... }예:
import { err } from 'neverthrow'
const myResult = err ( 'Oh noooo' ) // instance of `Err`
myResult . isOk ( ) // false
myResult . isErr ( ) // trueback 위로 돌아갑니다
Result.isOk (방법) 결과가 Ok 변형 인 경우 true 반환합니다
서명:
isOk ( ) : boolean { ... }back 위로 돌아갑니다
Result.isErr (방법) 결과가 Err variant 인 경우 true 를 반환합니다
서명 :
isErr ( ) : boolean { ... }back 위로 돌아갑니다
Result.map (메소드) 함수를 포함 된 Ok 값에 적용하여 < Result<U, E> Result<T, E> , e> 결과에 매핑하여 Err 값을 손대지 않게합니다.
이 기능은 두 기능의 결과를 작성하는 데 사용될 수 있습니다.
서명:
class Result < T , E > {
map < U > ( callback : ( value : T ) => U ) : Result < U , E > { ... }
}예 :
import { getLines } from 'imaginary-parser'
// ^ assume getLines has the following signature:
// getLines(str: string): Result<Array<string>, Error>
// since the formatting is deemed correct by `getLines`
// then it means that `linesResult` is an Ok
// containing an Array of strings for each line of code
const linesResult = getLines ( '1n2n3n4n' )
// this Result now has a Array<number> inside it
const newResult = linesResult . map (
( arr : Array < string > ) => arr . map ( parseInt )
)
newResult . isOk ( ) // trueback 위로 돌아갑니다
Result.mapErr (방법) 함수를 포함 된 Err 값에 적용하여 Result<T, E> Result<T, F> 를 맵핑하여 Ok 값을 손대지 않게합니다.
이 기능은 오류를 처리하면서 성공적인 결과를 통과하는 데 사용될 수 있습니다.
서명:
class Result < T , E > {
mapErr < F > ( callback : ( error : E ) => F ) : Result < T , F > { ... }
}예 :
import { parseHeaders } from 'imaginary-http-parser'
// imagine that parseHeaders has the following signature:
// parseHeaders(raw: string): Result<SomeKeyValueMap, ParseError>
const rawHeaders = 'nonsensical gibberish and badly formatted stuff'
const parseResult = parseHeaders ( rawHeaders )
parseResult . mapErr ( parseError => {
res . status ( 400 ) . json ( {
error : parseError
} )
} )
parseResult . isErr ( ) // trueback 위로 돌아갑니다
Result.unwrapOr (메소드) Ok 값을 풀거나 Err 있는 경우 기본값을 반환하십시오.
서명:
class Result < T , E > {
unwrapOr < T > ( value : T ) : T { ... }
}예 :
const myResult = err ( 'Oh noooo' )
const multiply = ( value : number ) : number => value * 2
const unwrapped : number = myResult . map ( multiply ) . unwrapOr ( 10 )back 위로 돌아갑니다
Result.andThen . 위의 map 와 동일한 아이디어. 새로운 Result 반환 해야하는 경우를 제외하고.
반환 된 값이 Result 입니다. v4.1.0-beta 기준으로 뚜렷한 오류 유형을 반환 할 수 있습니다 (아래 서명 참조). v4.1.0-beta 이전에 오류 유형은 별개 일 수 없습니다.
이것은 내부 T 값을 사용하여 후속 계산을 수행해야 할 때 유용하지만 해당 계산이 실패 할 수 있습니다.
andThen Result<Result<A, E2>, E1> Result<A, E2> 로 평평하게하는 도구로서 실제로 유용합니다 (아래 예제 참조).
서명:
class Result < T , E > {
// Note that the latest version lets you return distinct errors as well.
// If the error types (E and F) are the same (like `string | string`)
// then they will be merged into one type (`string`)
andThen < U , F > (
callback : ( value : T ) => Result < U , F >
) : Result < U , E | F > { ... }
}예 1 : 체인 결과
import { err , ok } from 'neverthrow'
const sq = ( n : number ) : Result < number , number > => ok ( n ** 2 )
ok ( 2 )
. andThen ( sq )
. andThen ( sq ) // Ok(16)
ok ( 2 )
. andThen ( sq )
. andThen ( err ) // Err(4)
ok ( 2 )
. andThen ( err )
. andThen ( sq ) // Err(2)
err ( 3 )
. andThen ( sq )
. andThen ( sq ) // Err(3)예제 2 : 평평한 중첩 결과
// It's common to have nested Results
const nested = ok ( ok ( 1234 ) )
// notNested is a Ok(1234)
const notNested = nested . andThen ( ( innerResult ) => innerResult )back 위로 돌아갑니다
Result.asyncAndThen (메소드) 새로운 ResultAsync 반환해야한다는 점을 제외하고 andThen 위와 같은 아이디어입니다.
반환 된 값은 ResultAsync 입니다.
서명:
class Result < T , E > {
asyncAndThen < U , F > (
callback : ( value : T ) => ResultAsync < U , F >
) : ResultAsync < U , E | F > { ... }
}back 위로 돌아갑니다
Result.orElse (방법) Err 값을 가져 와서 Result<T, SomeNewType> 에 맵핑하십시오. 오류 복구에 유용합니다.
서명:
class Result < T , E > {
orElse < U , A > (
callback : ( error : E ) => Result < U , A >
) : Result < U | T , A > { ... }
}예:
enum DatabaseError {
PoolExhausted = 'PoolExhausted' ,
NotFound = 'NotFound' ,
}
const dbQueryResult : Result < string , DatabaseError > = err ( DatabaseError . NotFound )
const updatedQueryResult = dbQueryResult . orElse ( ( dbError ) =>
dbError === DatabaseError . NotFound
? ok ( 'User does not exist' ) // error recovery branch: ok() must be called with a value of type string
//
//
// err() can be called with a value of any new type that you want
// it could also be called with the same error value
//
// err(dbError)
: err ( 500 )
)back 위로 돌아갑니다
Result.match (메소드) 주어진 2 개의 함수 ( Ok 변형의 경우 1 개, Err 변형의 경우 하나)는 Result 변형과 일치하는 함수를 실행합니다.
매치 콜백은 Result 반환 할 필요가 없지만 원하는 경우 Result 반환 할 수 있습니다.
서명:
class Result < T , E > {
match < A , B = A > (
okCallback : ( value : T ) => A ,
errorCallback : ( error : E ) => B
) : A | B => { ... }
} match chaining map 및 mapErr 와 같습니다. 두 함수 match 동일한 리턴 유형을 가져야한다는 구별입니다. match 와 체인 map 과 mapErr 의 차이점은 다음과 같습니다.
match 하면 두 기능 모두 동일한 리턴 유형 A 가 있어야합니다.match Result<T, E> A 로 일치시킵니다 (일치 함수의 리턴 유형)예:
// map/mapErr api
// note that you DON'T have to append mapErr
// after map which means that you are not required to do
// error handling
computationThatMightFail ( ) . map ( console . log ) . mapErr ( console . error )
// match api
// works exactly the same as above since both callbacks
// only perform side effects,
// except, now you HAVE to do error handling :)
computationThatMightFail ( ) . match ( console . log , console . error )
// Returning values
const attempt = computationThatMightFail ( )
. map ( ( str ) => str . toUpperCase ( ) )
. mapErr ( ( err ) => `Error: ${ err } ` )
// `attempt` is of type `Result<string, string>`
const answer = computationThatMightFail ( ) . match (
( str ) => str . toUpperCase ( ) ,
( err ) => `Error: ${ err } `
)
// `answer` is of type `string` 일치 콜백에서 오류 매개 변수를 사용하지 않으면 match unwrapOr 있는 체인 map 과 동일합니다.
const answer = computationThatMightFail ( ) . match (
( str ) => str . toUpperCase ( ) ,
( ) => 'ComputationError'
)
// `answer` is of type `string`
const answer = computationThatMightFail ( )
. map ( ( str ) => str . toUpperCase ( ) )
. unwrapOr ( 'ComputationError' )back 위로 돌아갑니다
Result.asyncMap (메소드) 두 가지를 제외하고 map 와 유사합니다.
Promise 반환해야합니다ResultAsync 반환합니다 그런 다음 ResultAsync API ( map , mapErr 및 andThen 등 등)를 사용하여 asyncMap 결과를 체인 할 수 있습니다.
서명:
class Result < T , E > {
asyncMap < U > (
callback : ( value : T ) => Promise < U >
) : ResultAsync < U , E > { ... }
}예:
import { parseHeaders } from 'imaginary-http-parser'
// imagine that parseHeaders has the following signature:
// parseHeaders(raw: string): Result<SomeKeyValueMap, ParseError>
const asyncRes = parseHeaders ( rawHeader )
. map ( headerKvMap => headerKvMap . Authorization )
. asyncMap ( findUserInDatabase ) 위의 예에서 parseHeaders Err 반환하면 .map 및 .asyncMap 이 호출되지 않으며 asyncRes 변수는 await 또는 .then() 사용하여 Result 로 바뀌면 Err 로 해결됩니다.
back 위로 돌아갑니다
Result.andTee (방법) Result<T, E> 를 취하고 전달 된 함수의 결과에 관계없이 원래 Result<T, E> 가 통과하도록합니다. 이것은 실패 또는 성공이 로깅과 같은 주요 논리에 영향을 미치지 않아야하는 부작용을 처리하는 편리한 방법입니다.
서명:
class Result < T , E > {
andTee (
callback : ( value : T ) => unknown
) : Result < T , E > { ... }
}예:
import { parseUserInput } from 'imaginary-parser'
import { logUser } from 'imaginary-logger'
import { insertUser } from 'imaginary-database'
// ^ assume parseUserInput, logUser and insertUser have the following signatures:
// parseUserInput(input: RequestData): Result<User, ParseError>
// logUser(user: User): Result<void, LogError>
// insertUser(user: User): ResultAsync<void, InsertError>
// Note logUser returns void upon success but insertUser takes User type.
const resAsync = parseUserInput ( userInput )
. andTee ( logUser )
. asyncAndThen ( insertUser )
// Note no LogError shows up in the Result type
resAsync . then ( ( res : Result < void , ParseError | InsertError > ) => { e
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User input has been parsed and inserted successfully." )
}
} ) )back 위로 돌아갑니다
Result.andThrough (메소드) 다음을 제외하고 andTee 와 유사합니다.
서명:
class Result < T , E > {
andThrough < F > (
callback : ( value : T ) => Result < unknown , F >
) : Result < T , E | F > { ... }
}예:
import { parseUserInput } from 'imaginary-parser'
import { validateUser } from 'imaginary-validator'
import { insertUser } from 'imaginary-database'
// ^ assume parseUseInput, validateUser and insertUser have the following signatures:
// parseUserInput(input: RequestData): Result<User, ParseError>
// validateUser(user: User): Result<void, ValidateError>
// insertUser(user: User): ResultAsync<void, InsertError>
// Note validateUser returns void upon success but insertUser takes User type.
const resAsync = parseUserInput ( userInput )
. andThrough ( validateUser )
. asyncAndThen ( insertUser )
resAsync . then ( ( res : Result < void , ParseErro | ValidateError | InsertError > ) => { e
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User input has been parsed, validated, inserted successfully." )
}
} ) )back 위로 돌아갑니다
Result.asyncAndThrough (메소드) resultasync를 반환 해야하는 것을 제외하고 andThrough 와 유사합니다.
그런 다음 ResultAsync API ( map , mapErr , andThen 등 등)를 사용하여 asyncAndThrough 결과를 징수 할 수 있습니다.
서명:
import { parseUserInput } from 'imaginary-parser'
import { insertUser } from 'imaginary-database'
import { sendNotification } from 'imaginary-service'
// ^ assume parseUserInput, insertUser and sendNotification have the following signatures:
// parseUserInput(input: RequestData): Result<User, ParseError>
// insertUser(user: User): ResultAsync<void, InsertError>
// sendNotification(user: User): ResultAsync<void, NotificationError>
// Note insertUser returns void upon success but sendNotification takes User type.
const resAsync = parseUserInput ( userInput )
. asyncAndThrough ( insertUser )
. andThen ( sendNotification )
resAsync . then ( ( res : Result < void , ParseError | InsertError | NotificationError > ) => { e
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User has been parsed, inserted and notified successfully." )
}
} ) )back 위로 돌아갑니다
Result.fromThrowable결과는 실제 JS 클래스는 아니지만,
fromThrowable구현 한 방식은Result에 대한 정적 방법 인 것처럼fromThrowable호출해야합니다. 아래 예제를 참조하십시오.
JavaScript 커뮤니티는 예외를 던지는 협약에 동의했습니다. 따라서 타사 라이브러리와 인터페이스 할 때 타사 코드를 Try / Catch 블록으로 래핑하는 것이 필수적입니다.
이 함수는 원래 함수가 던지면 Err 반환하는 새 기능을 만듭니다.
원래 함수에서 발생하는 오류의 유형을 알 수 없으므로 두 번째 인수 errorFn 사용하여 알려진 유형에 던져진 것을 매핑하는 것이 좋습니다.
예 :
import { Result } from 'neverthrow'
type ParseError = { message : string }
const toParseError = ( ) : ParseError => ( { message : "Parse Error" } )
const safeJsonParse = Result . fromThrowable ( JSON . parse , toParseError )
// the function can now be used safely, if the function throws, the result will be an Err
const res = safeJsonParse ( "{" ) ;back 위로 돌아갑니다
Result.combine (정적 클래스 방법)결과는 실제 JS 클래스는 아니지만
combine된 방법은Result에 대한 정적 메소드 인 것처럼combine호출해야합니다. 아래 예제를 참조하십시오.
Result 목록을 결합하십시오.
Promise.all 에 익숙하다면 All. Combine 기능은 개념적으로 동일하게 작동합니다.
이질적인 목록과 균질 한 목록에서 작업을 combine . 즉, 다른 종류의 Result 를 포함하고 여전히 결합 할 수있는 목록을 가질 수 있습니다. Result S 와 ResultAsync 를 모두 포함하는 목록을 결합 할 수 없습니다.
Combine 함수는 결과 목록을 가져 와서 단일 결과를 반환합니다. 목록의 모든 결과가 Ok 이면 모든 개별 Ok 값의 목록을 포함하는 반환 값이 Ok 됩니다.
목록의 결과 중 하나 만 Err 인 경우 COMBINE 함수는 ERR 값을 반환합니다 (단락 회로를보고 찾는 첫 번째 오류를 반환합니다).
공식적으로 말하기 :
// homogeneous lists
function combine < T , E > ( resultList : Result < T , E > [ ] ) : Result < T [ ] , E >
// heterogeneous lists
function combine < T1 , T2 , E1 , E2 > ( resultList : [ Result < T1 , E1 > , Result < T2 , E2 > ] ) : Result < [ T1 , T2 ] , E1 | E2 >
function combine < T1 , T2 , T3 , E1 , E2 , E3 > => Result < [ T1 , T2 , T3 ] , E1 | E2 | E3 >
function combine < T1 , T2 , T3 , T4 , E1 , E2 , E3 , E4 > => Result < [ T1 , T2 , T3 , T4 ] , E1 | E2 | E3 | E4 >
// ... etc etc ad infinitum예:
const resultList : Result < number , never > [ ] =
[ ok ( 1 ) , ok ( 2 ) ]
const combinedList : Result < number [ ] , unknown > =
Result . combine ( resultList )튜플의 예 :
/** @example tuple(1, 2, 3) === [1, 2, 3] // with type [number, number, number] */
const tuple = < T extends any [ ] > ( ... args : T ) : T => args
const resultTuple : [ Result < string , never > , Result < string , never > ] =
tuple ( ok ( 'a' ) , ok ( 'b' ) )
const combinedTuple : Result < [ string , string ] , unknown > =
Result . combine ( resultTuple )back 위로 돌아갑니다
Result.combineWithAllErrors (정적 클래스 메소드)결과는 실제 JS 클래스는 아니지만,
combineWithAllErrors구현 된 방식은Result에 대한 정적 메소드 인 것처럼combineWithAllErrors호출해야합니다. 아래 예제를 참조하십시오.
combine 처럼 단락없이. 첫 번째 오류 값 대신 입력 결과 목록의 모든 오류 값 목록이 나타납니다.
일부 결과 만 실패하면 새 결합 오류 목록에는 실패한 결과의 오차 값 만 포함하므로 새 오류 목록의 길이를 보장하지 않습니다.
기능 서명 :
// homogeneous lists
function combineWithAllErrors < T , E > ( resultList : Result < T , E > [ ] ) : Result < T [ ] , E [ ] >
// heterogeneous lists
function combineWithAllErrors < T1 , T2 , E1 , E2 > ( resultList : [ Result < T1 , E1 > , Result < T2 , E2 > ] ) : Result < [ T1 , T2 ] , ( E1 | E2 ) [ ] >
function combineWithAllErrors < T1 , T2 , T3 , E1 , E2 , E3 > => Result < [ T1 , T2 , T3 ] , ( E1 | E2 | E3 ) [ ] >
function combineWithAllErrors < T1 , T2 , T3 , T4 , E1 , E2 , E3 , E4 > => Result < [ T1 , T2 , T3 , T4 ] , ( E1 | E2 | E3 | E4 ) [ ] >
// ... etc etc ad infinitum예제 사용 :
const resultList : Result < number , string > [ ] = [
ok ( 123 ) ,
err ( 'boooom!' ) ,
ok ( 456 ) ,
err ( 'ahhhhh!' ) ,
]
const result = Result . combineWithAllErrors ( resultList )
// result is Err(['boooom!', 'ahhhhh!'])back 위로 돌아갑니다
Result.safeUnwrap()더 이상 사용되지 않았습니다 . 이 방법을 더 이상 사용할 필요가 없습니다.
Result 풀거나 Err 암시 적으로 반환하여 보일러 플레이트를 줄일 수 있습니다.
back 위로 돌아갑니다
ResultAsync ) okAsync ResultAsync 의 Ok 변형을 구성합니다
서명:
okAsync < T , E > ( value : T ) : ResultAsync < T , E >예:
import { okAsync } from 'neverthrow'
const myResultAsync = okAsync ( { myData : 'test' } ) // instance of `ResultAsync`
const myResult = await myResultAsync // instance of `Ok`
myResult . isOk ( ) // true
myResult . isErr ( ) // falseback 위로 돌아갑니다
errAsync ResultAsync 의 Err 변형을 구성합니다
서명:
errAsync < T , E > ( error : E ) : ResultAsync < T , E >예:
import { errAsync } from 'neverthrow'
const myResultAsync = errAsync ( 'Oh nooo' ) // instance of `ResultAsync`
const myResult = await myResultAsync // instance of `Err`
myResult . isOk ( ) // false
myResult . isErr ( ) // trueback 위로 돌아갑니다
ResultAsync.fromThrowable (정적 클래스 메소드) 결과 Promise 유사합니다.
예 :
import { ResultAsync } from 'neverthrow'
import { insertIntoDb } from 'imaginary-database'
// insertIntoDb(user: User): Promise<User>
const insertUser = ResultAsync . fromThrowable ( insertIntoDb , ( ) => new Error ( 'Database error' ) )
// `res` has a type of (user: User) => ResultAsync<User, Error> Promise 반환하는 모든 함수가 async 것은 아니기 때문에, 이는 거부 된 Promise 반환하는 대신 동시에 오류를 던질 수 있기 때문에 함수 호출의 결과와 함께 resultasync.promise를 사용하는 것보다 더 안전 할 수 있습니다. 예를 들어:
// NOT SAFE !!
import { ResultAsync } from 'neverthrow'
import { db } from 'imaginary-database'
// db.insert<T>(table: string, value: T): Promise<T>
const insertUser = ( user : User ) : Promise < User > => {
if ( ! user . id ) {
// this throws synchronously!
throw new TypeError ( 'missing user id' )
}
return db . insert ( 'users' , user )
}
// this will throw, NOT return a `ResultAsync`
const res = ResultAsync . fromPromise ( insertIntoDb ( myUser ) , ( ) => new Error ( 'Database error' ) )back 위로 돌아갑니다
ResultAsync.fromPromise (정적 클래스 메소드) PromiseLike<T> (던질 수 있음) ResultAsync<T, E> 로 변환합니다.
두 번째 인수는 약속의 거부 사례를 처리하고 unknown 의 오류를 일부 유형 E 로 매핑합니다.
서명:
// fromPromise is a static class method
// also available as a standalone function
// import { fromPromise } from 'neverthrow'
ResultAsync . fromPromise < T , E > (
promise : PromiseLike < T > ,
errorHandler : ( unknownError : unknown ) => E )
) : ResultAsync < T , E > { ... } 사실에 대해 알고 있는 PromiseLike 객체로 작업하는 경우, 중복 errorHandler 인수를 전달하지 않기 위해 fromSafePromise 사용하십시오.
예 :
import { ResultAsync } from 'neverthrow'
import { insertIntoDb } from 'imaginary-database'
// insertIntoDb(user: User): Promise<User>
const res = ResultAsync . fromPromise ( insertIntoDb ( myUser ) , ( ) => new Error ( 'Database error' ) )
// `res` has a type of ResultAsync<User, Error>back 위로 돌아갑니다
ResultAsync.fromSafePromise (정적 클래스 메소드) 약속의 거부를 처리하지 않는다는 점을 제외하고는 ResultAsync.fromPromise 으로 결과와 동일합니다. 당신이하고있는 일을 알고 있는지 확인하십시오. 그렇지 않으면이 약속에 던져진 예외는 결과를 해결하는 대신 resultasync가 거부하게됩니다.
서명:
// fromPromise is a static class method
// also available as a standalone function
// import { fromPromise } from 'neverthrow'
ResultAsync . fromSafePromise < T , E > (
promise : PromiseLike < T >
) : ResultAsync < T , E > { ... }예 :
import { RouteError } from 'routes/error'
// simulate slow routes in an http server that works in a Result / ResultAsync context
// Adopted from https://github.com/parlez-vous/server/blob/2496bacf55a2acbebc30631b5562f34272794d76/src/routes/common/signup.ts
export const slowDown = < T > ( ms : number ) => ( value : T ) =>
ResultAsync . fromSafePromise < T , RouteError > (
new Promise ( ( resolve ) => {
setTimeout ( ( ) => {
resolve ( value )
} , ms )
} )
)
export const signupHandler = route < User > ( ( req , sessionManager ) =>
decode ( userSignupDecoder , req . body , 'Invalid request body' ) . map ( ( parsed ) => {
return createUser ( parsed )
. andThen ( slowDown ( 3000 ) ) // slowdown by 3 seconds
. andThen ( sessionManager . createSession )
. map ( ( { sessionToken , admin } ) => AppData . init ( admin , sessionToken ) )
} )
)back 위로 돌아갑니다
ResultAsync.map (메소드) 함수를 포함 된 Ok 값에 적용하여 ResultAsync<T, E> ResultAsync<U, E> 맵핑하여 Err 값을 손대지 않게합니다.
적용된 함수는 반환 유형에 영향을 미치지 않고 동기식 또는 비동기식 ( Promise<U> 반환) 일 수 있습니다.
이 기능은 두 기능의 결과를 작성하는 데 사용될 수 있습니다.
서명:
class ResultAsync < T , E > {
map < U > (
callback : ( value : T ) => U | Promise < U >
) : ResultAsync < U , E > { ... }
}예 :
import { findUsersIn } from 'imaginary-database'
// ^ assume findUsersIn has the following signature:
// findUsersIn(country: string): ResultAsync<Array<User>, Error>
const usersInCanada = findUsersIn ( "Canada" )
// Let's assume we only need their names
const namesInCanada = usersInCanada . map ( ( users : Array < User > ) => users . map ( user => user . name ) )
// namesInCanada is of type ResultAsync<Array<string>, Error>
// We can extract the Result using .then() or await
namesInCanada . then ( ( namesResult : Result < Array < string > , Error > ) => {
if ( namesResult . isErr ( ) ) {
console . log ( "Couldn't get the users from the database" , namesResult . error )
}
else {
console . log ( "Users in Canada are named: " + namesResult . value . join ( ',' ) )
}
} )back 위로 돌아갑니다
ResultAsync.mapErr (메소드) 함수를 포함 된 Err 값에 적용하여 ResultAsync<T, E> 를 ResultAsync<T, F> 에 맵핑하여 Ok 값을 그대로 유지합니다.
적용된 함수는 반환 유형에 영향을 미치지 않고 동기식 또는 비동기식 ( Promise<F> 반환) 일 수 있습니다.
이 기능은 오류를 처리하면서 성공적인 결과를 통과하는 데 사용될 수 있습니다.
서명:
class ResultAsync < T , E > {
mapErr < F > (
callback : ( error : E ) => F | Promise < F >
) : ResultAsync < T , F > { ... }
}예 :
import { findUsersIn } from 'imaginary-database'
// ^ assume findUsersIn has the following signature:
// findUsersIn(country: string): ResultAsync<Array<User>, Error>
// Let's say we need to low-level errors from findUsersIn to be more readable
const usersInCanada = findUsersIn ( "Canada" ) . mapErr ( ( error : Error ) => {
// The only error we want to pass to the user is "Unknown country"
if ( error . message === "Unknown country" ) {
return error . message
}
// All other errors will be labelled as a system error
return "System error, please contact an administrator."
} )
// usersInCanada is of type ResultAsync<Array<User>, string>
usersInCanada . then ( ( usersResult : Result < Array < User > , string > ) => {
if ( usersResult . isErr ( ) ) {
res . status ( 400 ) . json ( {
error : usersResult . error
} )
}
else {
res . status ( 200 ) . json ( {
users : usersResult . value
} )
}
} )back 위로 돌아갑니다
ResultAsync.unwrapOr (메소드) Ok 값을 풀거나 Err 있으면 기본값을 반환하십시오.
Result.unwrapOr 와 마찬가지로 작동하지만 T 대신 Promise<T> 반환합니다.
서명:
class ResultAsync < T , E > {
unwrapOr < T > ( value : T ) : Promise < T > { ... }
}예 :
const unwrapped : number = await errAsync ( 0 ) . unwrapOr ( 10 )
// unwrapped = 10back 위로 돌아갑니다
ResultAsync.andThen (메소드) 위의 map 와 동일한 아이디어. 적용된 함수를 제외하고는 Result 또는 ResultAsync 반환해야합니다.
ResultAsync.andThen and and then and then은 응용 기능의 리턴 유형에 관계없이 항상 ResultAsync 반환합니다.
이것은 내부 T 값을 사용하여 후속 계산을 수행해야 할 때 유용하지만 해당 계산이 실패 할 수 있습니다.
andThen ResultAsync<ResultAsync<A, E2>, E1> ResultAsync<A, E2> 로 평평하게하는 도구로서 정말 유용합니다 (아래 예제 참조).
서명:
// Note that the latest version (v4.1.0-beta) lets you return distinct errors as well.
// If the error types (E and F) are the same (like `string | string`)
// then they will be merged into one type (`string`)
class ResultAsync < T , E > {
andThen < U , F > (
callback : ( value : T ) => Result < U , F > | ResultAsync < U , F >
) : ResultAsync < U , E | F > { ... }
}예
import { validateUser } from 'imaginary-validator'
import { insertUser } from 'imaginary-database'
import { sendNotification } from 'imaginary-service'
// ^ assume validateUser, insertUser and sendNotification have the following signatures:
// validateUser(user: User): Result<User, Error>
// insertUser(user): ResultAsync<User, Error>
// sendNotification(user): ResultAsync<void, Error>
const resAsync = validateUser ( user )
. andThen ( insertUser )
. andThen ( sendNotification )
// resAsync is a ResultAsync<void, Error>
resAsync . then ( ( res : Result < void , Error > ) => {
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User has been validated, inserted and notified successfully." )
}
} )back 위로 돌아갑니다
ResultAsync.orElse (메소드) Err 값을 가져 와서 ResultAsync<T, SomeNewType> 에 맵핑하십시오. 오류 복구에 유용합니다.
서명:
class ResultAsync < T , E > {
orElse < U , A > (
callback : ( error : E ) => Result < U , A > | ResultAsync < U , A >
) : ResultAsync < U | T , A > { ... }
}back 위로 돌아갑니다
ResultAsync.match (메소드) 주어진 2 개의 함수 ( Ok 변형의 경우 1 개, Err 변형의 경우 하나)는 ResultAsync 변형과 일치하는 함수를 실행합니다.
결과와의 차이점은 Result.match 으로 ResultAsync 의 비동기 특성으로 인해 항상 Promise 반환한다는 것입니다.
서명:
class ResultAsync < T , E > {
match < A , B = A > (
okCallback : ( value : T ) => A ,
errorCallback : ( error : E ) => B
) : Promise < A | B > => { ... }
}예:
import { validateUser } from 'imaginary-validator'
import { insertUser } from 'imaginary-database'
// ^ assume validateUser and insertUser have the following signatures:
// validateUser(user: User): Result<User, Error>
// insertUser(user): ResultAsync<User, Error>
// Handle both cases at the end of the chain using match
const resultMessage = await validateUser ( user )
. andThen ( insertUser )
. match (
( user : User ) => `User ${ user . name } has been successfully created` ,
( error : Error ) => `User could not be created because ${ error . message } `
)
// resultMessage is a stringback 위로 돌아갑니다
ResultAsync.andTee (메소드) ResultAsync<T, E> 를 취하고 전달 된 함수의 결과에 관계없이 원래 ResultAsync<T, E> 통과하게합니다. 이것은 실패 또는 성공이 로깅과 같은 주요 논리에 영향을 미치지 않아야하는 부작용을 처리하는 편리한 방법입니다.
서명:
class ResultAsync < T , E > {
andTee (
callback : ( value : T ) => unknown
) : ResultAsync < T , E > => { ... }
}예:
import { insertUser } from 'imaginary-database'
import { logUser } from 'imaginary-logger'
import { sendNotification } from 'imaginary-service'
// ^ assume insertUser, logUser and sendNotification have the following signatures:
// insertUser(user: User): ResultAsync<User, InsertError>
// logUser(user: User): Result<void, LogError>
// sendNotification(user: User): ResultAsync<void, NotificationError>
// Note logUser returns void on success but sendNotification takes User type.
const resAsync = insertUser ( user )
. andTee ( logUser )
. andThen ( sendNotification )
// Note there is no LogError in the types below
resAsync . then ( ( res : Result < void , InsertError | NotificationError > ) => { e
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User has been inserted and notified successfully." )
}
} ) ) back 위로 돌아갑니다
ResultAsync.andThrough (메소드) 다음을 제외하고 andTee 와 유사합니다.
서명:
class ResultAsync < T , E > {
andThrough < F > (
callback : ( value : T ) => Result < unknown , F > | ResultAsync < unknown , F > ,
) : ResultAsync < T , E | F > => { ... }
}예:
import { buildUser } from 'imaginary-builder'
import { insertUser } from 'imaginary-database'
import { sendNotification } from 'imaginary-service'
// ^ assume buildUser, insertUser and sendNotification have the following signatures:
// buildUser(userRaw: UserRaw): ResultAsync<User, BuildError>
// insertUser(user: User): ResultAsync<void, InsertError>
// sendNotification(user: User): ResultAsync<void, NotificationError>
// Note insertUser returns void upon success but sendNotification takes User type.
const resAsync = buildUser ( userRaw )
. andThrough ( insertUser )
. andThen ( sendNotification )
resAsync . then ( ( res : Result < void , BuildError | InsertError | NotificationError > ) => { e
if ( res . isErr ( ) ) {
console . log ( "Oops, at least one step failed" , res . error )
}
else {
console . log ( "User data has been built, inserted and notified successfully." )
}
} ) ) back 위로 돌아갑니다
ResultAsync.combine (정적 클래스 방법) ResultAsync 의 목록을 결합하십시오.
Promise.all 에 익숙하다면 All. Combine 기능은 개념적으로 동일하게 작동합니다.
이질적인 목록과 균질 한 목록에서 작업을 combine . 즉, 다양한 종류의 ResultAsync 를 포함하고 여전히 결합 할 수있는 목록을 가질 수 있습니다. Result S 와 ResultAsync 를 모두 포함하는 목록을 결합 할 수 없습니다.
Combine 함수는 결과 목록을 가져 와서 단일 결과를 반환합니다. 목록의 모든 결과가 Ok 이면 모든 개별 Ok 값의 목록을 포함하는 반환 값이 Ok 됩니다.
목록의 결과 중 하나 만 Err 인 경우 COMBINE 함수는 ERR 값을 반환합니다 (단락 회로를보고 찾는 첫 번째 오류를 반환합니다).
공식적으로 말하기 :
// homogeneous lists
function combine < T , E > ( resultList : ResultAsync < T , E > [ ] ) : ResultAsync < T [ ] , E >
// heterogeneous lists
function combine < T1 , T2 , E1 , E2 > ( resultList : [ ResultAsync < T1 , E1 > , ResultAsync < T2 , E2 > ] ) : ResultAsync < [ T1 , T2 ] , E1 | E2 >
function combine < T1 , T2 , T3 , E1 , E2 , E3 > => ResultAsync < [ T1 , T2 , T3 ] , E1 | E2 | E3 >
function combine < T1 , T2 , T3 , T4 , E1 , E2 , E3 , E4 > => ResultAsync < [ T1 , T2 , T3 , T4 ] , E1 | E2 | E3 | E4 >
// ... etc etc ad infinitum예:
const resultList : ResultAsync < number , never > [ ] =
[ okAsync ( 1 ) , okAsync ( 2 ) ]
const combinedList : ResultAsync < number [ ] , unknown > =
ResultAsync . combine ( resultList )튜플의 예 :
/** @example tuple(1, 2, 3) === [1, 2, 3] // with type [number, number, number] */
const tuple = < T extends any [ ] > ( ... args : T ) : T => args
const resultTuple : [ ResultAsync < string , never > , ResultAsync < string , never > ] =
tuple ( okAsync ( 'a' ) , okAsync ( 'b' ) )
const combinedTuple : ResultAsync < [ string , string ] , unknown > =
ResultAsync . combine ( resultTuple )back 위로 돌아갑니다
ResultAsync.combineWithAllErrors (정적 클래스 메소드) combine 처럼 단락없이. 첫 번째 오류 값 대신 입력 결과 목록의 모든 오류 값 목록이 나타납니다.
일부 결과 만 실패하면 새 결합 오류 목록에는 실패한 결과의 오차 값 만 포함하므로 새 오류 목록의 길이를 보장하지 않습니다.
기능 서명 :
// homogeneous lists
function combineWithAllErrors < T , E > ( resultList : ResultAsync < T , E > [ ] ) : ResultAsync < T [ ] , E [ ] >
// heterogeneous lists
function combineWithAllErrors < T1 , T2 , E1 , E2 > ( resultList : [ ResultAsync < T1 , E1 > , ResultAsync < T2 , E2 > ] ) : ResultAsync < [ T1 , T2 ] , ( E1 | E2 ) [ ] >
function combineWithAllErrors < T1 , T2 , T3 , E1 , E2 , E3 > => ResultAsync < [ T1 , T2 , T3 ] , ( E1 | E2 | E3 ) [ ] >
function combineWithAllErrors < T1 , T2 , T3 , T4 , E1 , E2 , E3 , E4 > => ResultAsync < [ T1 , T2 , T3 , T4 ] , ( E1 | E2 | E3 | E4 ) [ ] >
// ... etc etc ad infinitum예제 사용 :
const resultList : ResultAsync < number , string > [ ] = [
okAsync ( 123 ) ,
errAsync ( 'boooom!' ) ,
okAsync ( 456 ) ,
errAsync ( 'ahhhhh!' ) ,
]
const result = ResultAsync . combineWithAllErrors ( resultList )
// result is Err(['boooom!', 'ahhhhh!']) ResultAsync.safeUnwrap()더 이상 사용되지 않았습니다 . 이 방법을 더 이상 사용할 필요가 없습니다.
Result 풀거나 Err 암시 적으로 반환하여 보일러 플레이트를 줄일 수 있습니다.
back 위로 돌아갑니다
fromThrowable Result.fromThrowable 의 최상위 수준 내보내기. 결과에서 문서를 찾으십시오
back 위로 돌아갑니다
fromAsyncThrowable roomSrowable의 ResultAsync.fromThrowable 의 최상위 수출. romethrowable에서 resultasync.에서 문서를 찾으십시오
back 위로 돌아갑니다
fromPromise ResultAsync.fromPromise 의 resultasync의 최상위 수출 수출. resultasync.fromPromise에서 문서를 찾으십시오
back 위로 돌아갑니다
fromSafePromise ResultAsync.fromSafePromise 의 최상위 수출. resultasync.fromsafepromise에서 문서를 찾으십시오
back 위로 돌아갑니다
safeTry암시 적으로 오류를 반환하고 보일러 플레이트를 줄이는 데 사용됩니다.
Result 반환하는 함수를 작성한다고 가정 해 봅시다. 그 기능에서 우리는 Result 를 반환하는 일부 함수를 호출하고 결과를 확인하여 계속 진행 해야하는지 확인 해야하는지 확인합니다. 일반적으로 우리는 다음과 같이 쓸 것입니다.
declare function mayFail1 ( ) : Result < number , string > ;
declare function mayFail2 ( ) : Result < number , string > ;
function myFunc ( ) : Result < number , string > {
// We have to define a constant to hold the result to check and unwrap its value.
const result1 = mayFail1 ( ) ;
if ( result1 . isErr ( ) ) {
return err ( `aborted by an error from 1st function, ${ result1 . error } ` ) ;
}
const value1 = result1 . value
// Again, we need to define a constant and then check and unwrap.
const result2 = mayFail2 ( ) ;
if ( result2 . isErr ( ) ) {
return err ( `aborted by an error from 2nd function, ${ result2 . error } ` ) ;
}
const value2 = result2 . value
// And finally we return what we want to calculate
return ok ( value1 + value2 ) ;
} 기본적으로 각 결과에 대해 상수를 정의하여 확인 Ok 를 확인하고 .value 또는 .error 를 읽습니다.
보호를 통해 우리는 ' Err 있으면 여기에 반환 할 수 있습니다. 그렇지 않으면 여기에 랩을 풀고 계속 진행하십시오.' 단 하나의 표현으로.
declare function mayFail1 ( ) : Result < number , string > ;
declare function mayFail2 ( ) : Result < number , string > ;
function myFunc ( ) : Result < number , string > {
return safeTry < number , string > ( function * ( ) {
return ok (
// If the result of mayFail1().mapErr() is an `Err`, the evaluation is
// aborted here and the enclosing `safeTry` block is evaluated to that `Err`.
// Otherwise, this `(yield* ...)` is evaluated to its `.value`.
( yield * mayFail1 ( )
. mapErr ( e => `aborted by an error from 1st function, ${ e } ` ) )
+
// The same as above.
( yield * mayFail2 ( )
. mapErr ( e => `aborted by an error from 2nd function, ${ e } ` ) )
)
} )
} safeTry 사용하기 위해 포인트는 다음과 같습니다.
yield* <RESULT> 사용하여 'return <RESULT> .value 하면 ErrsafeTry 로 전달하십시오 비동기 발전기 기능을 사용하여 비동기 블록을 전달하여 safeTry 수도 있습니다.
// You can use either Promise<Result> or ResultAsync.
declare function mayFail1 ( ) : Promise < Result < number , string > > ;
declare function mayFail2 ( ) : ResultAsync < number , string > ;
function myFunc ( ) : Promise < Result < number , string > > {
return safeTry < number , string > ( async function * ( ) {
return ok (
// You have to await if the expression is Promise<Result>
( yield * ( await mayFail1 ( ) )
. mapErr ( e => `aborted by an error from 1st function, ${ e } ` ) )
+
// You can call `safeUnwrap` directly if its ResultAsync
( yield * mayFail2 ( )
. mapErr ( e => `aborted by an error from 2nd function, ${ e } ` ) )
)
} )
}자세한 내용은 #448 및 #444를 참조하십시오
back 위로 돌아갑니다
Result 인스턴스에는 _unsafeUnwrap 및 _unsafeUnwrapErr 라고 불리는 두 가지 안전하지 않은 방법이 있습니다.
_unsafeUnwrap Result<T, E> 가져 와서 결과가 Ok 되면 T 반환하고 그렇지 않으면 사용자 정의 객체를 던집니다.
_unsafeUnwrapErr Result<T, E> 가져 와서 결과가 Err 일 때 E 반환하고 그렇지 않으면 사용자 정의 객체를 던집니다.
그렇게하면 다음과 같은 작업을 수행 할 수 있습니다.
expect ( myResult . _unsafeUnwrap ( ) ) . toBe ( someExpectation ) 그러나 Result 인스턴스는 비슷합니다. 따라서 테스트에서 기대치를 주장하기 위해 반드시 풀릴 필요는 없습니다. 그래서 당신은 다음과 같은 일을 할 수 있습니다.
import { ok } from 'neverthrow'
// ...
expect ( callSomeFunctionThatReturnsAResult ( "with" , "some" , "args" ) ) . toEqual ( ok ( someExpectation ) ) ; 기본적으로 던진 값에는 스택 트레이스가 포함되어 있지 않습니다. 스택 추적 생성은 농담에서 오류 메시지를 이해하기 어렵 기 때문입니다. 스택 추적을 생성하려면 구성 객체로 _unsafeUnwrap 및 / 또는 _unsafeUnwrapErr 호출하십시오.
_unsafeUnwrapErr ( {
withStackTrace : true ,
} )
// ^ Now the error object will have a `.stack` property containing the current stack이 패키지가 유용하다고 생각되면 저를 후원하거나 단순히 커피를 사는 것을 고려하십시오!
패키지는 neverthrow 라고하지만 말 그대로 가져 가지 마십시오. 나는 단순히 개발자가 쓰고있는 소프트웨어의 인체 공학과 사용에 대해 조금 더 생각하도록 격려하고 있습니다.
Throw 와 catching goto 진술을 사용하는 것과 매우 유사합니다. 그것은 당신의 프로그램에 대한 추론을 더 어렵게 만듭니다. 둘째, throw 사용하여 기능의 발신자가 catch 구현하고 있다고 가정합니다. 이것은 알려진 오류의 원인입니다. 예 : 하나의 개발자 throw 와 다른 개발자는 기능이 던질 사전 지식없이 기능을 사용합니다. 따라서 에지 케이스가 손가락을 깎지 않고 이제 불행한 사용자, 보스, 고양이 등이 있습니다.
모든 말로, 프로그램에 던질 수있는 좋은 사용 사례가 있습니다. 그러나 당신이 생각하는 것보다 훨씬 적습니다.
NeverThrow 프로젝트는 MIT 라이센스의 조건에 따라 오픈 소스로 제공됩니다.