2分钟搞定JS面试 / 承诺

2025-06-08

2分钟搞定JS面试 / 承诺

问题:
什么是承诺

快速回答:
它是一个表示操作当前状态和值的对象。Promises 有三种状态:待处理、成功、失败。

更长的答案:
基本上,Promises 背后的想法相当容易理解。它只是一个容器,只有在某些计算完成后才会解析。就是这样。

我想如果我们自己实现它就会更容易理解。

class MyPromise {
    dataHandlers = []
    errorHandler = []
    finalHandlers = []

    constructor(func) {
        // Apply handlers one by one and initialize every following handler with the previouses result
        let onResolve = data => this.dataHandlers.reduce(
            (acc, onData) => onData(acc), 
            data
        )
        // Just call every onReject
        let onReject = error => this.errorHandler.reduce(
            (_, onError) => onError(error),
            undefined
        )
        // Just call every onFinal
        let onFinal = () => this.finalHandlers.reduce(
            (_, onFinal) => onFinal(), 
            undefined
        )

        // We need to set timeout, so our function
        // executed after we set .then, .catch, and .finally
        setTimeout(() => {
            try {
                func(onResolve, onReject)
            } catch (error) {
                onReject(error)
            } finally {
                onFinal()
            }
        }, 0)
    }

    then(onData, onError) {
        if (onData) { this.dataHandlers.push(onData) }
        if (onError) { this.errorHandler.push(onError) }
        return this
    }

    catch(onError) {
        return this.then(undefined, onError)
    }

    finally(onFinal) {
        if (onFinal) { this.finalHandlers.push(onFinal) }
        return this
    }
}
Enter fullscreen mode Exit fullscreen mode

让我们测试一下!

let dataPromise = new MyPromise((resolve, reject) => resolve(2))
dataPromise
    .then(res => res + 2)
    .then(res => res * 2)
    .then(res => console.log(res)) // 8
    .finally(() => console.log('Finally!')) // Finally!
    .finally(() => console.log('Finally (1)!')) // Finally (1)!

let rejectPromise = new MyPromise((resolve, reject) => reject(2))
rejectPromise
    .then(res => res + 2)
    .then(res => res * 2)
    .then(res => console.log(res))
    .catch(error => console.error(error)) // 2
    .finally(() => console.log('Finally!')) // Finally!

let throwErrorPromise = new MyPromise((resolve, reject) => { throw new Error('hello') })
throwErrorPromise
    .then(res => res + 2)
    .then(res => res * 2)
    .then(res => console.log(res))
    .catch(error => console.error(error)) // hello
    .finally(() => console.log('Finally!')) // Finally

// This one will produce two errors instead of one.
// Can you come up with the fix?
let doubleErrorPromise = new MyPromise((resolve, reject) => reject('first'))
doubleErrorPromise
    .catch(error => { console.error(error); throw 'second' })
// 'first'
// 'second'
// Uncaught 'second'

// This is how it should work
let fixedDoubleErrorPromise = new Promise((resolve, reject) => reject('first'))
fixedDoubleErrorPromise
    .catch(error => { console.error(error); throw 'second' })
// 'first'
// Uncaught 'second'
Enter fullscreen mode Exit fullscreen mode

实际应用:
有时使用async/await 语法会更容易一些

有时你会需要 Promise 辅助函数,例如Promise.all

资源:
MDN/Promise

其他帖子:


顺便说一句,我会在这里和推特上发布更多有趣的东西。我们做个朋友吧👋

鏂囩珷鏉ユ簮锛�https://dev.to/hexnickk/js-interview-in-2-minutes-promise-4fhl
PREV
2 分钟内完成 JS 面试 / 这个🤯
NEXT
2 分钟内完成 JS 面试 / 记忆法 💭