setTimeout은 콜백 함수입니다.만약 우리가 이 점을 바꾼다면, 무슨 일이 일어날까요?
오늘날 노드식 리셋 함수를 승낙식 함수로 바꾸는 것은 흔히 볼 수 있는 방법이다.그렇다면 왜 우리는
setTimeout
을 위해 이 일을 하지 않았습니까?노드식 리셋에 비해 승낙식 함수를 선호하는 주요 원인은 Callback Hell을 피하기 위해서다.
아무도 그걸 보고 싶지 않아요.
setTimeout
(그리고 그의 형제 setInterval
또는 setImmediate
)을 본 후에 나는 그것이 리셋 스타일의 함수라는 것을 똑똑히 볼 수 있다.setTimeout(callback, 1000);
// --------
// \
// See that? Right there. A callback!
그러나 setTimeout
을 리셋에서 약속으로 바꾸는 사람은 드물다.setTimeout
은 어떻게 레이더 아래에서 비행합니까?setTimeout
의 차이로 통행증을 얻을 수 있습니까?아니요.
노드 스타일 콜백 함수setTimeout
은 분명히 리셋 스타일의 함수이지만 노드 스타일의 리셋 함수가 아니기 때문에 무시될 수 있습니다.
우선 노드 스타일의 리셋을 살펴보고 차이를 잘 이해하자.fs.readFile
은 노드식 리셋 함수의 좋은 예이다.
fs.readFile(path[, options], callback)
// --------
// /
// callback must be last
콜백 자체는 다음과 같이 해야 합니다.
const callback = (err, data) => { /* ... */ }
// --- ----
// / \
// error first data last
만약에 setTimeout
이 전통적인 노드 스타일 리셋 함수라면 노드의 util.promisify
을 쉽게 사용하여 전환할 수 있다.다음 예는 util.promisify
을 사용하여 fs.readFile
을 승낙식 함수로 바꾸는 것이 얼마나 쉬운지 설명한다.
import fs from 'fs'
import { promisify } from 'util'
const readFile = promisify(fs.readFile)
불행히도 util.promisify
은 일을 할 수 없을 것이다.우선, 리셋은 마지막 인자가 아니기 때문이다.그 다음으로 리셋은 (err, data)
인터페이스를 따르지 않기 때문이다.
알림 설정 시간 초과
다행히도 수동 전환도 간단하다.나는 새 함수 sleep
을 호출할 것이다.
const sleep = milliseconds => value => new Promise (resolve =>
setTimeout(() => resolve(value), milliseconds)
)
이 코드에 관해서 나는 몇 가지 관건적인 일을 지적하고 싶다.
fs.readFile(path[, options], callback)
// --------
// /
// callback must be last
const callback = (err, data) => { /* ... */ }
// --- ----
// / \
// error first data last
import fs from 'fs'
import { promisify } from 'util'
const readFile = promisify(fs.readFile)
다행히도 수동 전환도 간단하다.나는 새 함수
sleep
을 호출할 것이다.const sleep = milliseconds => value => new Promise (resolve =>
setTimeout(() => resolve(value), milliseconds)
)
이 코드에 관해서 나는 몇 가지 관건적인 일을 지적하고 싶다.sleep
은 카레입니다.이따가 이유를 알게 될 거야.sleep
에서 value
을 취한 다음에 value
을 해석한다.다시 한 번 말하지만, 너는 이따가 원인을 알게 될 것이다.수면
이제 코드에 일시 정지를 추가하는 것은 약속을 사용하는 것처럼 간단합니다.
const log => msg => console.log(msg)
sleep(1000)('Hello World').then(log)
이것은 매우 좋지만, 내가 이 글을 쓴 원인은 아니다.sleep
에 대해 진정으로 나를 흥분시키는 것은 그것을 약속 체인의 중간에 미끄러뜨릴 수 있다는 것이다.
이 예에서는 API 호출 사이에 1초 지연을 추가하는 것이 간단합니다.
import axios from 'axios'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
// -
// /
// comma operator. google it.
fetchJson('https://swapi.co/api/people/1')
.then(log)
.then(sleep(1000))
.then(() => fetchJson('https://swapi.co/api/people/2'))
.then(log)
.then(sleep(1000))
.then(() => fetchJson('https://swapi.co/api/people/3'))
.then(log)
sleep
은 하나의 값을 입력으로 받아들이고 같은 값을 되돌려주기 때문에 이 값을 다음 약속에 전달합니다.sleep
은 기본적으로 승낙체인 중간부품이 되었다.
비동기식/대기 모드로 작성된 것을 살펴보겠습니다.
import axios from 'axios'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const main = async () => {
const people1 = await fetchJson('https://swapi.co/api/people/1')
log(people1)
await sleep(1000)
const people2 = await fetchJson('https://swapi.co/api/people/2')
log(people2)
await sleep(1000)
const people3 = await fetchJson('https://swapi.co/api/people/3')
log(people3)
}
main()
솔직히 말하면, 나는 sleep
이 해결한 문제를 좋아하지만, 나는 내가 방금 보여 준 코드의 문법을 그다지 좋아하지 않는다.이 두 가지 예에서 나는 사실 async/await
의 문법이 더 나쁘다고 생각한다.await
은 도처에 널려 있어 실수하기 쉽다.
비동기 함수 합성
함수 조합 기능이 강해서 많은 문장을 읽어야만 완전히 이해할 수 있을 것이다.그저 그렇다는 것이 아니라 왜다.만약 네가 시작하고 싶다면, 나는 여기서부터 시작할 것을 건의한다. Functional JavaScript: Function Composition For Every Day Use .
나는 본문에서 함수 구성을 해석하지 않으려고 한다.나는 내가 너희들에게 보여줄 문법이 매우 간단하다고 믿는다. 너희들은 함수의 구성을 이해할 필요가 전혀 없다.
import axios from 'axios'
import pipe from 'mojiscript/core/pipe'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const main = pipe ([
() => fetchJson('https://swapi.co/api/people/1'),
log,
sleep(1000),
() => fetchJson('https://swapi.co/api/people/2'),
log,
sleep(1000),
() => fetchJson('https://swapi.co/api/people/3'),
log
])
main()
빌어먹을!이것은 보기 좋은 코드들이다!
그러나 우리는 이미 함수 조합을 토론하고 있기 때문에 fetchJson
, log
, sleep
을 자신의 pipe
에서 추출하여 코드를 더욱 건조하게 하기 쉽다.
import axios from 'axios'
import pipe from 'mojiscript/core/pipe'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const fetchLogWait = pipe ([
id => fetchJson (`https://swapi.co/api/people/${id}`),
log,
sleep(1000)
])
const main = pipe ([
() => fetchLogWait (1),
() => fetchLogWait (2),
() => fetchLogWait (3)
])
main()
비동기식 매핑
또한 MojiScript는 비동기식 매핑의 고유한 기능을 제공합니다.(머지않아 이 방면에 관한 글 한 편이 나올 것으로 예상된다.)
비동기 매핑은 내가 MojiScript의 pipe
이 아니라 Ramda의 pipeP
을 사용하여 이 예시들을 작성하기로 결정한 이유이다.지금까지 람다의 pipeP
의 예도 잘 사용할 수 있다.이 점에서 예는 Mojiscript가 독점하고 있습니다.
코드 좀 봅시다!비동기 map
ajax 호출은 얼마나 쉽습니까?
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map (fetchLogWait),
])
main ({ start: 1, end: 3 })
아주 간단해!
실행 가능한 코드 블록:
import axios from 'axios'
import log from 'mojiscript/console/log'
import pipe from 'mojiscript/core/pipe'
import map from 'mojiscript/list/map'
import range from 'mojiscript/list/range'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = pipe ([
axios.get,
response => response.data
])
const fetchLogWait = pipe ([
id => fetchJson (`https://swapi.co/api/people/${id}`),
log,
sleep (1000)
])
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map(fetchLogWait),
])
main ({ start: 1, end: 3 })
지금, 이 코드는 이미 매우 무미건조해졌다!
for 사이클에서 시간 초과 설정
현재 이 문제를 보지 못했다면 많은 자바스크립트 인터뷰에서 이 문제를 볼 수 있습니다.코드가 예상대로 실행되지 않았습니다.출력은 무엇입니까?
for (var i = 1; i < 6; i++) {
setTimeout(() => console.log(i), 1000)
}
만약 그것이 1초를 멈추고 한 번에 5개의 6
을 출력할 것이라고 생각하지 못했다면, 당신은 틀렸다.pipe
과 Mojiscript의 map
을 사용하여 동일한 프로그램을 작성합니다.이외에도 이 기능은 예상대로 작동하며, 매번 출력하기 전에 1초의 정지로 1부터 5까지 인쇄됩니다.
const sleepThenLog = pipe ([
sleep (1000),
log
])
const main = pipe ([
range (1) (6),
map (sleepThenLog)
])
더 하고 싶어요?
구글 얘기.
const log => msg => console.log(msg)
sleep(1000)('Hello World').then(log)
import axios from 'axios'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
// -
// /
// comma operator. google it.
fetchJson('https://swapi.co/api/people/1')
.then(log)
.then(sleep(1000))
.then(() => fetchJson('https://swapi.co/api/people/2'))
.then(log)
.then(sleep(1000))
.then(() => fetchJson('https://swapi.co/api/people/3'))
.then(log)
import axios from 'axios'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const main = async () => {
const people1 = await fetchJson('https://swapi.co/api/people/1')
log(people1)
await sleep(1000)
const people2 = await fetchJson('https://swapi.co/api/people/2')
log(people2)
await sleep(1000)
const people3 = await fetchJson('https://swapi.co/api/people/3')
log(people3)
}
main()
함수 조합 기능이 강해서 많은 문장을 읽어야만 완전히 이해할 수 있을 것이다.그저 그렇다는 것이 아니라 왜다.만약 네가 시작하고 싶다면, 나는 여기서부터 시작할 것을 건의한다. Functional JavaScript: Function Composition For Every Day Use .
나는 본문에서 함수 구성을 해석하지 않으려고 한다.나는 내가 너희들에게 보여줄 문법이 매우 간단하다고 믿는다. 너희들은 함수의 구성을 이해할 필요가 전혀 없다.
import axios from 'axios'
import pipe from 'mojiscript/core/pipe'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const main = pipe ([
() => fetchJson('https://swapi.co/api/people/1'),
log,
sleep(1000),
() => fetchJson('https://swapi.co/api/people/2'),
log,
sleep(1000),
() => fetchJson('https://swapi.co/api/people/3'),
log
])
main()
빌어먹을!이것은 보기 좋은 코드들이다!그러나 우리는 이미 함수 조합을 토론하고 있기 때문에
fetchJson
, log
, sleep
을 자신의 pipe
에서 추출하여 코드를 더욱 건조하게 하기 쉽다.import axios from 'axios'
import pipe from 'mojiscript/core/pipe'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = url => axios.get(url).then(response => response.data)
const log = msg => (console.log(msg), msg)
const fetchLogWait = pipe ([
id => fetchJson (`https://swapi.co/api/people/${id}`),
log,
sleep(1000)
])
const main = pipe ([
() => fetchLogWait (1),
() => fetchLogWait (2),
() => fetchLogWait (3)
])
main()
비동기식 매핑
또한 MojiScript는 비동기식 매핑의 고유한 기능을 제공합니다.(머지않아 이 방면에 관한 글 한 편이 나올 것으로 예상된다.)
비동기 매핑은 내가 MojiScript의 pipe
이 아니라 Ramda의 pipeP
을 사용하여 이 예시들을 작성하기로 결정한 이유이다.지금까지 람다의 pipeP
의 예도 잘 사용할 수 있다.이 점에서 예는 Mojiscript가 독점하고 있습니다.
코드 좀 봅시다!비동기 map
ajax 호출은 얼마나 쉽습니까?
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map (fetchLogWait),
])
main ({ start: 1, end: 3 })
아주 간단해!
실행 가능한 코드 블록:
import axios from 'axios'
import log from 'mojiscript/console/log'
import pipe from 'mojiscript/core/pipe'
import map from 'mojiscript/list/map'
import range from 'mojiscript/list/range'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = pipe ([
axios.get,
response => response.data
])
const fetchLogWait = pipe ([
id => fetchJson (`https://swapi.co/api/people/${id}`),
log,
sleep (1000)
])
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map(fetchLogWait),
])
main ({ start: 1, end: 3 })
지금, 이 코드는 이미 매우 무미건조해졌다!
for 사이클에서 시간 초과 설정
현재 이 문제를 보지 못했다면 많은 자바스크립트 인터뷰에서 이 문제를 볼 수 있습니다.코드가 예상대로 실행되지 않았습니다.출력은 무엇입니까?
for (var i = 1; i < 6; i++) {
setTimeout(() => console.log(i), 1000)
}
만약 그것이 1초를 멈추고 한 번에 5개의 6
을 출력할 것이라고 생각하지 못했다면, 당신은 틀렸다.pipe
과 Mojiscript의 map
을 사용하여 동일한 프로그램을 작성합니다.이외에도 이 기능은 예상대로 작동하며, 매번 출력하기 전에 1초의 정지로 1부터 5까지 인쇄됩니다.
const sleepThenLog = pipe ([
sleep (1000),
log
])
const main = pipe ([
range (1) (6),
map (sleepThenLog)
])
더 하고 싶어요?
구글 얘기.
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map (fetchLogWait),
])
main ({ start: 1, end: 3 })
import axios from 'axios'
import log from 'mojiscript/console/log'
import pipe from 'mojiscript/core/pipe'
import map from 'mojiscript/list/map'
import range from 'mojiscript/list/range'
import sleep from 'mojiscript/threading/sleep'
const fetchJson = pipe ([
axios.get,
response => response.data
])
const fetchLogWait = pipe ([
id => fetchJson (`https://swapi.co/api/people/${id}`),
log,
sleep (1000)
])
const main = pipe ([
({ start, end }) => range (start) (end + 1),
map(fetchLogWait),
])
main ({ start: 1, end: 3 })
현재 이 문제를 보지 못했다면 많은 자바스크립트 인터뷰에서 이 문제를 볼 수 있습니다.코드가 예상대로 실행되지 않았습니다.출력은 무엇입니까?
for (var i = 1; i < 6; i++) {
setTimeout(() => console.log(i), 1000)
}
만약 그것이 1초를 멈추고 한 번에 5개의 6
을 출력할 것이라고 생각하지 못했다면, 당신은 틀렸다.pipe
과 Mojiscript의 map
을 사용하여 동일한 프로그램을 작성합니다.이외에도 이 기능은 예상대로 작동하며, 매번 출력하기 전에 1초의 정지로 1부터 5까지 인쇄됩니다.const sleepThenLog = pipe ([
sleep (1000),
log
])
const main = pipe ([
range (1) (6),
map (sleepThenLog)
])
더 하고 싶어요?구글 얘기.
총결산
sleep를promise 스타일로 변환하는 함수는 비동기 코드 실행 방식의 추가 옵션을 제공합니다.
Ramda의 pipeP
또는 Mojiscript의 pipe
은 때때로 Promises
또는 async/await
보다 더 깨끗하다.
비동기식 매핑 기능이 강력합니다.
아래에서 지적한 경고는 이런 실현은 취소를 허락하지 않는다는 것이다.따라서 clearTimeout
이 필요한 경우 이 함수를 수정해야 합니다.
제 글은 모두 기능성이 강한 자바스크립트입니다. 더 필요하시면 저를 따라오세요. 아니면 트위터로 오세요!
내 기타 기사 읽기:
How I rediscovered my love for JavaScript after throwing 90% of it in the trash
Reference
이 문제에 관하여(setTimeout은 콜백 함수입니다.만약 우리가 이 점을 바꾼다면, 무슨 일이 일어날까요?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/joelnet/settimeout-is-a-callback-style-function-what-would-happen-if-we-change-that-3fei
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(setTimeout은 콜백 함수입니다.만약 우리가 이 점을 바꾼다면, 무슨 일이 일어날까요?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/joelnet/settimeout-is-a-callback-style-function-what-would-happen-if-we-change-that-3fei텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)