龙空技术网

深入理解Promise

ZC超超 385

前言:

现时姐妹们对“递归promise”大约比较着重,兄弟们都需要分析一些“递归promise”的相关文章。那么小编也在网摘上收集了一些关于“递归promise””的相关资讯,希望大家能喜欢,同学们一起来了解一下吧!

promise.all的用法

const promiseResove = (promiseResolveSecond = function(n=0){    return new Promise(function(resolve, reject){        setTimeout(function() {            resolve({                resolveAfterSeconds: n            })        }, n * 100);    })})const promiseReject = (promiseRejectSecond = function(n=0) {    return new Promise(function(resolve, reject) {        setTimeout(function () {            reject({                rejectAfterSeconds: n            })        }, n * 100)    })})var promiseArray = []promiseArray.push(promiseResove(1))promiseArray.push(promiseReject(3))promiseArray.push(promiseResove(2))

这里有个问题;如果有一个失败了;就不会返回其他promise的正常结果;这不是我们想要的结果;

// 将传入promise.all的数组进行遍历,如果catch住reject结果,// 直接返回,这样就可以在最后结果中将所有结果都获取到var handlePromise = Promise.all(promiseArray.map(function(promiseItem) {    return promiseItem.catch(function(err) {      return err    })}))handlePromise.then(function(values) {    console.log('all promise are resolved', values)}).catch(function(reason) {    console.log('promise reject failed reason', reason)})

再精简一下

//最终精简过后的promise.all的err改装(其实原理很简单,我自己的错我先捕获到,我用then传递出去; b用法二)export function handlePromise(promiseArray) {    return Promise.all(promiseArray.map(promiseItem=> promiseItem.catch(err=>err)))}

promise.all 的各种用法:

  a.用法一let p = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p1')    }, 1000);}).then(res=>{    return  '这是p1的then'})let p2 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p2')    }, 2000);})let p3 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p3')    }, 3000);})Promise.all([p,p2,p3]).then(res=>{    console.log(res)})输出:0: "这是p1的then"1: "这是p2"2: "这是p3"    b.用法二let p = new Promise((resolve,reject)=>{    setTimeout(() => {        reject('这是p1')    }, 1000);}).catch(err=>{    return 'p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧'})let p2 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p2')    }, 2000);})let p3 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p3')    }, 3000);})Promise.all([p,p2,p3]).then(res=>{    console.log(res)})输出:0: "p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧"1: "这是p2"2: "这是p3"        c.用法三    let p = new Promise((resolve,reject)=>{    setTimeout(() => {        reject('这是p1')    }, 1000);}).catch(err=>{    return 'p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧'})let p2 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p2')    }, 2000);})let p3 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p3')    }, 3000);})let p4 = {    then:function(a){        a(20)    }}let p5 = {        a:1}Promise.all([p,p2,p3,p4,p5]).then(res=>{    console.log(res)})输出:0: "p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧"1: "这是p2"2: "这是p3"3: 204: {a: 1}进一步let p = new Promise((resolve,reject)=>{    setTimeout(() => {        reject('这是p1')    }, 1000);}).catch(err=>{    return 'p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧'})let p2 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p2')    }, 2000);})let p3 = new Promise((resolve,reject)=>{    setTimeout(() => {        resolve('这是p3')    }, 3000);})let p4 = {    then:function(a){        let p6 = {            then:function(b){                b(80)            }        }        a(p6)    }}let p5 = {    a:1}Promise.all([p,p2,p3,p4,p5]).then(res=>{    console.log(res)})输出:0: "p1虽然我reject了,但是我自己捕获了,传递给then你继续执行吧"1: "这是p2"2: "这是p3"3: 804: {a: 1}

手写Promise

function Promise(fn) {    /**     * state: 保存状态       * pedding 等待     * fulfilled  成功状态     * rejected 失败     */    let state = 'pending'    /**     * value :返回值 或者说 在then 链式回调里传递的值(对错都有)     */    let value = null    /**     * 保存函数数组     */    const callbacks = []    /**     * then(最关键的部分): 接收两个函数; resolve reject 函数 永远返回的是 promise 函数 方便连缀     */    this.then = function (onFulfilled, onRejected) {        return new Promise((resolve, reject) => {            /**             * 注意这里是同步的             * 不要以为promise 全都是异步的             * 初代promise 的同步内容 为同步的             */            handle({                onFulfilled,                onRejected,                resolve,                reject,            })        })    }    /**     * catch  : 执行catch  就是 执行then 但是不传第一个resolve函数     */    this.catch = function (onError) {        this.then(null, onError)    }    /***     * finally 函数 就是 then 但是resovle 和 reject 都执行 这个函数     */    this.finally = function (onDone) {        this.then(onDone, onDone)    }    /**     * resolve  和 reject  立地成promise     */    this.resolve = function (value) {        // 如果value 是 promise 就直接返回        if (value && value instanceof Promise) {            return value        }        // object  而且 object的then 还为函数        if (value && typeof value === 'object' && typeof value.then === 'function') {            const { then } = value            // 返回肯定为promise 且 value.then接收一个函数:这个函数是resolve;resolve 接收一个参数,这个参数就then(res=>{res就为这个此参数})            return new Promise((resolve) => {                then(resolve)            })        }        // 如果有value 且 不满足上面条件 就 返回 value        if (value) {            return new Promise(resolve => resolve(value))        }        // 否者返回一个空        return new Promise(resolve => resolve())    }    /**     * reject  相对 resolve 简单 catch err == value     */    this.reject = function (value) {        return new Promise(((resolve, reject) => {            reject(value)        }))    }    /**     * 全部接收 promise  等待全部promise 返回成功 就返回     */    this.all = function (arr) {        // 确定转化为数组        const args = Array.prototype.slice.call(arr)        // 无论什么情况下都是返回 promise        return new Promise(((resolve, reject) => {            // 如果没传 就返回 空[]            if (args.length === 0) return resolve([])            let remaining = args.length            function res(i, val) {                /**                 * 这个地方有意思了                 */                try {                    /**                     * promise 都会进入 这个if 但是进入了这个if 的不一定都是Promise                     * 当然我也不在乎, 谁来我都收                     */                    if (val && (typeof val === 'object' || typeof val === 'function')) {                        const { then } = val                        /**                         * 这个地方厉害了                         * 如果你是对象 或者 promise                         * 我要取 then                         * 而且你的then 要还必须的是函数                         * 如何确定promise then已经执行完毕就是重点了                         */                        if (typeof then === 'function') {                            /**                             * 这个地方就有意思了,call必须bind this                             * 如果他的then时函数的话 到这里都会被return 掉的.                             * 在res函数里形成一个递归 ; 但reject会一下打断 promise 所以一个错其余的皆错                             */                            then.call(val, (val) => {                                /**                                 * res的目的                                 * 为了then执行的时候 计数 和 打破闭包                                 * 但是如果你的val 任然满足 结构出then且时函数的话                                 * 会继续闭包下去,且不会被计数                                 * 一旦计数 就确定不满足条件,                                 * 且这条链路上的promise都执行到了then打破闭包                                 */                                res(i, val)                            }, reject)                            return                        }                    }                    /**                     * 其他情况下:原路返回,                     */                    args[i] = val                    /**                     * 即使前面有递归; 但是只有一个满足下面的判断,打断                     */                    if (--remaining === 0) { //等待所有的args 执行完 就resolve args 数组                        resolve(args)                    }                } catch (ex) {                    reject(ex)                }            }            // 遍历执行 res  接收下标 和 对应的 promise            for (let i = 0; i < args.length; i++) {                res(i, args[i])            }        }))    }    /**     * race 相比 all 简单多了     * resovle 和 reject 执行一个 立即打断promise     *     */    this.race = function (values) {        return new Promise(((resolve, reject) => {            for (let i = 0, len = values.length; i < len; i++) {                values[i].then(resolve, reject)            }        }))    }    /**     * 下面这三个就是promise 的构成了很重要     * callback 为对象     * 据我分析:对象包含4个值     * onFulfilled 成功的函数     * onRejected 失败的函数     * resolve 打破promise的成功条件     * reject 打破promise的失败条件     * 只有handle 可以想callbacks 添加callback     */    function handle(callback) {        // 如果在pedding状态下就把callback 添加到callbacks        if (state === 'pending') {            callbacks.push(callback)            return        }        /**         * 下面两个const         * cb为需要执行的函数         * next为 打断promise 的函数         */        const cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected        const next = state === 'fulfilled' ? callback.resolve : callback.reject        /**         * 如何你没有传cb         * 就打断promise,并且打断 handle 函数         * 继续传递给下一个promise         */        if(!cb) {            next(value)            return        }        /**         * 否者         * 把cb 函数的返回值传给下一个 next         */        try {            const ret = cb(value)            next(ret)        } catch (e) {            callback.reject(e)        }    }    /**     * resolve 函数     * 理解上面会对你理解这个有帮助     * setTimeout 确保你promise 怎么处理都是异步的,不可能同步     * 同样 resolve 和reject 和其他函数刚刚相反,它只在不是pedding的状态下执行     * 同样 ; 它照单接收 你传入任何类型的值     * 但是     * resolve 接收的是promise或者满足条件的对象函数     * 他会递归执行到最后     * 就是说 返回的是一个确定的同步的值;     */    function resolve(newValue) {          const fn = () => {            if (state !== 'pending') return            if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {                const { then } = newValue                if (typeof then === 'function') {                    /**                     * 此处为递归                     * 所以一定要有不满足条件的 !== function                     * 否者会一直pedding                     *                     */                    then.call(newValue, resolve, reject)                    return                }            }            state = 'fulfilled'            // 替换value 为链路传递的值            value = newValue            handelCb()        }        setTimeout(fn, 0)    }    /**     *     * 同理: 几乎和 resolve 相反一摸一样     */    function reject(error) {           const fn = () => {            if (state !== 'pending') return            if (error && (typeof error === 'object' || typeof error === 'function')) {                const { then } = error                if (typeof then === 'function') {                    then.call(error, resolve, reject)                    return                }            }            state = 'rejected'            value = error            handelCb()        }        setTimeout(fn, 0)    }    /**     * 遍历执行 callbacks 里的函数     * 执行一个删除一个     * 知道callbacks.length 为0     */    function handelCb() {        while (callbacks.length) {            const fn = callbacks.shift()            handle(fn)        }    }    fn(resolve, reject) //启动}

标签: #递归promise