LHJ

I'm a FE developer.

14.3.4 프로미스 체인

21 May 2020 » js_lj

14.3.4 프로미스 체인

프로미스에는 체인으로 연결할 수 있다는 장점이 있습니다.
즉, 프로미스가 완료되면 다른 프로미스를 반환하는 함수를 즉시 호출할 수 있습니다.
launch 함수를 만들어 카운트다운이 끝나면 실행되게 해 봅시다.

function launch() {
    return new Promise(function(resolve, reject) {
        console.log("Lift off!");
        setTimeout(function() {
            resolve("In orbit!");
        }, 2*1000); // 2초만에 궤도에 도달하다니!
    })
}

이 함수를 카운트다운에 쉽게 묶을 수 있습니다.

const EventEmitter = require('events').EventEmitter;

class Countdown extends EventEmitter {
    constructor(seconds, superstitious) {
        super();
        this.seconds = seconds;
        this.superstitious = !!superstitious;
    }
    go() {
        const countdown = this;
        const timeoutIds = [];
        return new Promise(function(resolve, reject) {
            for (let i=countdown.seconds; i>=0; i--) {
                timeoutIds.push(setTimeout(function() {
                    if (countdown.superstitious && i===13) {
                        // 대기중인 타임아웃을 모두 취소합니다.
                        timeoutIds.forEach(clearTimeout);
                        return reject(new Error('Oh my god'));
                    }
                    countdown.emit('tick', i);
                    if (i===0) resolve();
                }, (countdown.seconds - i) * 1000))
            }
        })
    }
}

function launch() {
    return new Promise(function(resolve, reject) {
        console.log("Lift off!");
        setTimeout(function() {
            resolve("In orbit!");
        }, 2*1000); // 2초만에 궤도에 도달하다니!
    })
}

const c = new Countdown(5)
    .on('tick', i => console.log(i + '...'));

c.go()
    .then(launch)
    .then(function(msg) {
        console.log(msg);
    })
    .catch(function(err) {
        console.error("Houston, we have a problem...");
    })

프로미스 체인을 사용하면 모든 단계에서 에러를 캐치할 필요는 없습니다.
체인 어디에서든 에러가 생기면 체인 전체가 넘기고 catch 핸들러가 동작합니다.
카운트다운을 15초로 바꾸고 superstitious(미신)을 넣어서 실행해 보십시오.
launch는 실행되지 않습니다.

const EventEmitter = require('events').EventEmitter;

class Countdown extends EventEmitter {
    constructor(seconds, superstitious) {
        super();
        this.seconds = seconds;
        this.superstitious = !!superstitious;
    }
    go() {
        const countdown = this;
        const timeoutIds = [];
        return new Promise(function(resolve, reject) {
            for (let i=countdown.seconds; i>=0; i--) {
                timeoutIds.push(setTimeout(function() {
                    if (countdown.superstitious && i===13) {
                        // 대기중인 타임아웃을 모두 취소합니다.
                        timeoutIds.forEach(clearTimeout);
                        return reject(new Error('Oh my god'));
                    }
                    countdown.emit('tick', i);
                    if (i===0) resolve();
                }, (countdown.seconds - i) * 1000))
            }
        })
    }
}

function launch() {
    return new Promise(function(resolve, reject) {
        console.log("Lift off!");
        setTimeout(function() {
            resolve("In orbit!");
        }, 2*1000); // 2초만에 궤도에 도달하다니!
    })
}

const c = new Countdown(15, true)
    .on('tick', i => console.log(i + '...'));

c.go()
    .then(launch)
    .then(function(msg) {
        console.log(msg);
    })
    .catch(function(err) {
        console.error("Houston, we have a problem...");
    })