향상된 API 및 ReScript
ReScript (이전에는 BuckleScript) 은 정적 유형의 음성 언어, 컴파일러, 구축 시스템으로 매우 읽을 수 있는 자바스크립트를 생성한다.따라서 타자 구멍을 참을 수 없는 사람들에게는 타자 스크립트의 절호의 대체품이다.
ReScript는 JavaScript API에 쉽게 바인딩할 수 있도록 다양한 데코더를 제공합니다.
최근에 나는 브라우저의
mediaDevices
API을 사용하도록 요구받았다.가장 중요한 방법 중 하나는 getUserMedia
방법으로 MediaStream
대상을 포함하는 약속을 생성한다.API 사용자가 오디오, 비디오를 요청하는지 또는 오디오와 비디오를 동시에 요청하는지 확인하는 데 필요한 매개 변수 constraints
객체도 있습니다.예를 들어, 오디오 스트림만 요청하려면 다음 JS 코드를 사용할 수 있습니다.navigator.mediaDevices.getUserMedia({audio: true, video: false})
비디오에만 audio: false, video: true
을 설정하고 두 가지가 필요한 경우에만 audio: true, video: true
을 설정합니다.이러한 API는 일반적인 ReScript에서 다음 방법 중 하나로 설계될 수 있습니다.
constraints
변형:type constraints = Audio | Video | Both
let getUserMedia: constraints => Js.Promise.t<stream> = ...
/* Calling the function */
getUserMedia(Audio)
getUserMedia(Video)
getUserMedia(Both)
let getUserAudio: unit => Js.Promise.t<stream> = ...
let getUserVideo: unit => Js.Promise.t<stream> = ...
let getUserMedia: unit => Js.Promise.t<stream> = ...
/* Calling the function */
getUserAudio()
getUserVideo()
getUserMedia()
이런 상황에서 나는 후자를 더욱 좋아한다.곧 알게 될 거야, 왜.바깥쪽을 껴안다
기존 JS 함수에 연결하는 기본 방식은 external 키워드를 사용하고 일련의 다른 수식자/주석을 덧붙이는 것입니다. 항상
@
으로 시작합니다.NOTE: With the most current bundle of the ReScript platform (bs-platform 8.3), it will be possible to omit the
bs
part in the annotations. So@bs.as
will turn to just@as
, etc. Check if your version is new enough for even cleaner code.
바인딩 시도 1
navigator.mediaDevices.getUserMedia
등 전역 값에 귀속시키려면 두 개의 주석이 필요합니다.귀속을 어떻게 작성하는지 보고 나중에 여러 부분으로 분해합시다./* Navigator.MediaDevices module */
type constraints = {
audio: bool,
video: bool,
}
@bs.val @bs.scope(("navigator", "mediaDevices"))
external _getUserMedia: constraints => Js.Promise.t<stream> =
"getUserMedia"
type constraints = ...
: 첫 번째 부분은
getUserMedia
함수에 대한 제약 매개 변수의 유형 정의입니다.그것은 이른바 기록으로 하나의 대상처럼 보이고 같은 모양의 JS 대상으로 컴파일되었지만 실제로는 something different이다.@bs.val
이 글로벌 값에 바인딩됩니다.글로벌 값은 범위 내에서 항상 존재하는 값입니다(예: navigator
또는 window
).물론 이것은 목표 플랫폼(브라우저, 노드 등)에 달려 있다.@bs.scope(("navigator", "mediaDevices"))
: 이 값을 끼워 넣을 때도 @bs.scope
을 사용하여 그 범위를 정의해야 한다.여기에서, 우리는 컴파일러의 역할 영역이 다차원적이라는 문자열 그룹을 사용합니다.((
과 ))
은 쌍원조이기 때문에 하나의 원조임을 알 수 있다.외원괄호는 scope 함수에서 왔고, 내원괄호는tuple에서 왔다.또는 다음 내용을 나타내는 문자열을 사용할 수도 있습니다: @bs.scope("navigator.mediaDevices")
.external _getUserMedia
: 위 주석은 external
키워드와 함께 사용됩니다.바인딩할 JavaScript 메서드와 같을 필요가 없는 바인딩의 이름을 정의할 수 있습니다.: constraints => Js.Promise.t<stream>
: 그리고 유형 주석.MDN에 따르면 앞에서 언급한constraints 대상을 받아들이고 미디어스트림의 약속을 되돌려줍니다. 이 약속은 내장된 ReScript 유형 Js.Promise.t
으로 전환됩니다.유감스럽게도promise로 포장된 <stream>
유형은 내장된 것이 아니지만 이에 상응하여 입력할 수 있다(독자에게 연습용으로 남겨준다)😉). = "getUserMedia"
: 마지막으로 함수의 실제 이름을 가진 문자열입니다.타자 오류를 조심해라!현재 우리는
getUserMedia
까지 귀속되어 있지만 코드 라이브러리 중 어느 곳에서든 추악한 Navigator.MediaDevices._getUserMedia({audio: true, video: true}
이라고 부르고 싶습니까, 아니면 우리가 더 좋은 API를 실현할 수 있을까요?도움말 함수를 작성해 보겠습니다.
/* Navigator.MediaDevices module continued */
let getUserAudio = () => _getUserMedia({audio: true, video: false})
let getUserVideo = () => _getUserMedia({audio: false, video: true})
let getUserMedia = () => _getUserMedia({audio: true, video: true})
그런 다음 다음 다음 코드 라이브러리의 모든 위치에서 이러한 함수를 호출할 수 있습니다.Navigator.MediaDevices.getUserAudio()
Navigator.MediaDevices.getUserVideo()
Navigator.MediaDevices.getUserMedia()
NOTE: Simplified example, in practice you would use
Js.Promise.then_
or the like, to retrieve the stream itself.
아, 많이 좋아진 것 같아.그런데 지금 저희가 추가 코드를 만들었어요.
예를 들어 이 함수는
function getUserAudio(param) {
return navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
}
바인딩 시도 2
우리는 더 잘할 수 있을 뿐만 아니라, 기본 매개 변수로 함수를 채울 수 있습니까?그래, 이 예쁜 수작으로.
실체에 복잡한 이름을 붙여야 한다면 만들 수 없는 아주 유용한
@bs.as
주석이 있습니다.예를 들어 기록 필드에서 -
을 사용할 수 없습니다. 이 주석을 통해 완화할 수 있습니다.@bs.as
은 단일 문자열을 매개 변수로 사용합니다.공교롭게도 JSON은 기본적으로 복잡한 문자열일 뿐이기 때문에 우리는 일부 복잡한 대상을 기본 설정에 주입할 수 있다.그냥 쓰세요.
@bs.as(json`{your-config-object}`)
이후 _
호출 함수를 사용할 때 이 값을 무시합니다.그 밖에 우리는 최종
unit
(함수의 유일한'매개 변수')을 추가했다./* Navigator.MediaDevices module */
@bs.val @bs.scope(("navigator", "mediaDevices"))
external getUserAudio: (
@bs.as(json`{"audio": false, "video": true}`) _,
unit,
) => Js.Promise.t<stream> = "getUserMedia"
하지만 내가 말한 JSON 기교에도 한계가 있다.배열, 객체, 문자열, 숫자 및 부울 값과 같은 JSON 값에만 적용됩니다.예를 들어, 함수가 작동하지 않습니다.다른 두 가지 가능한 기능에 대해 동일한 작업을 수행할 수 있습니다.
/* Navigator.MediaDevices module continued */
@bs.val @bs.scope(("navigator", "mediaDevices"))
external getUserVideo: (
@bs.as(json`{"audio": true, "video": false}`) _,
unit,
) => Js.Promise.t<stream> = "getUserMedia"
@bs.val @bs.scope(("navigator", "mediaDevices"))
external getUserMedia: (
@bs.as(json`{"audio": true, "video": true}`) _,
unit,
) => Js.Promise.t<stream> = "getUserMedia"
결국 시도 1과 동일한 API가 제공됩니다.마찬가지로 우리는 이전과 같이 함수를 호출할 수 있다.Navigator.MediaDevices.getUserAudio()
Navigator.MediaDevices.getUserVideo()
Navigator.MediaDevices.getUserMedia()
그러나 이번에 부품을 구축하지 않았기 때문에 두 번째 시도의 원가는 0이었다🎉. 경험치 법칙:
let
은 추가 JS 코드를 생성하고 external
은 생성하지 않습니다.당신들의 독서에 감사드립니다. 나는 이 기교가 당신들 중 일부에게 도움이 되기를 바랍니다.간단명료한 예를 들어 이 블로그가 바탕으로 한 ReScript playground example을 보십시오.
Reference
이 문제에 관하여(향상된 API 및 ReScript), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/fhammerschmidt/nicer-apis-with-rescript-361텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)