Following on from the promiseA+ rip-off implementation, promise has a few syntactic sugar implementations outside of the spec

catch finally resolve reject race all

The implementation code

catch

MyPromise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected)
}
Copy the code

The test code

new MyPromise((resolve, reject) = > {
    reject('err')
}).catch((reason) = > {
    console.log(reason) // err

    return 'data'
}).then((value) = > {
    console.log(value) // data
})
Copy the code

resolve

MyPromise.resolve = (data) = > {
    // If data is a promise, return it directly
    if (data instanceof MyPromise) {
        return data
    } else {
        return new MyPromise(resolve= > {
            resolve(data)
        })
    }
}
Copy the code

The test code

MyPromise.resolve(2).then((data) = > {
    console.log(data) / / 2
})

MyPromise.resolve(
    new MyPromise((resolve, reject) = > {
        reject(5)
    })
).catch((data) = > {
    console.log(data) / / 5
})
Copy the code

reject

// As opposed to promise. resolve, reject directly
MyPromise.reject = (reason) = > {
    return new MyPromise((resolve, reject) = > {
        reject(reason)
    })
}
Copy the code

The test code

MyPromise.reject(2).catch((reason) = > {
    console.log(reason) / / 2
})
Copy the code

finally

MyPromise.prototype.finally = function (callback) {
    return this.then((value) = > {
        // callback has no arguments.
        // If the callback returns a PROMISE, it waits for the promise to execute
        return MyPromise.resolve(callback()).then((a)= > {
            // Finally keeps the promise state and value
            return value
        })
    }, (reason) => {
        return MyPromise.resolve(callback()).then((a)= > {
            // Finally keeps the promise state and value
            throw reason
        })
    })
}
Copy the code

The test code

MyPromise.resolve(2).finally((value) = > {
    console.log(value) // undefined
}).then((value) = > {
    console.log(value) / / 2
})

MyPromise.reject(2).finally((reason) = > {
    console.log(reason) // undefined
}).catch((reason) = > {
    console.log(reason) / / 2
})

MyPromise.resolve(2).finally((value) = > {
    return new MyPromise((resolve) = > {
        setTimeout((a)= > {
            resolve(100)},1000)
    })
}).then((value) = > {
    console.log(value) / / 100
})
Copy the code

all

MyPromise.all = (paramList) = > {
    const len = paramList.length
    const result = []
    let count = 0

    return new MyPromise((resolve, reject) = > {
        // The length of the argument is 0
        if (len === 0) resolve(result)

        paramList.forEach((param, index) = > {
            // If the array element is not a promise, it is wrapped as a promise
            MyPromise.resolve(param).then((value) = > {
                count++
                result[index] = value

                if (count === len) {
                    resolve(result)
                }
            }, (reason) => {
                reject(reason)
            })
        })
    })
}
Copy the code

The test code

const p1 = new MyPromise((resolve) = > {
    setTimeout((a)= > {
        resolve(3)},2000)})const p2 = new MyPromise((resolve) = > {
    setTimeout((a)= > {
        resolve(4)},1000)})const p3 = new MyPromise((resolve, reject) = > {
    setTimeout((a)= > {
        reject(5)},1000)
})


MyPromise.all([
    1.2, p1, p2
]).then((value) = > {
    console.log(value) // [1, 2, 3, 4]
})

MyPromise.all([
    1.2, p1, p2, p3
]).catch((reason) = > {
    console.log(reason) / / 5
})

MyPromise.all([]).then((value) = > {
    console.log(value) / / []
})
Copy the code

race

MyPromise.race = (paramList) = > {
    return new MyPromise((resolve, reject) = > {
        // An empty array is kept in wait state
        if (paramList.length === 0) return

        paramList.forEach((param) = > {
            Promise.resolve(param).then((value) = > {
                resolve(value)
            }, (reason) => {
                reject(reason)
            })
        })
    })
}
Copy the code

The test code

const p1 = new MyPromise((resolve) = > {
    setTimeout((a)= > {
        resolve(1)},1000)})const p2 = new MyPromise((resolve) = > {
    setTimeout((a)= > {
        resolve(2)},2000)})const p3 = new MyPromise((resolve, reject) = > {
    setTimeout((a)= > {
        reject(3)},500)
})

MyPromise.race([]).then(value= > {
    console.log(value)
}, reason => {
    console.log(reason)
})

MyPromise.race([1.2]).then(value= > {
    console.log(value) / / 1
}, reason => {
    console.log(reason)
})

MyPromise.race([p1, 4]).then(value= > {
    console.log(value) / / 4
}, reason => {
    console.log(reason)
})

MyPromise.race([p1, p2]).then(value= > {
    console.log(value) / / 1
}, reason => {
    console.log(reason)
})

MyPromise.race([p1, p3]).then(value= > {
    console.log(value)
}, reason => {
    console.log(reason) / / 3
})
Copy the code

reference

  • proposal-promise-finally

  • Source code implementation of Promise (perfect compliance with the Promise/A+ specification)

  • Hand-write A Promise/A+ that passes the official 872 test cases flawlessly


Welcome to the front end learning punch group learning ~ 516913974