首页 > 编程语言 >异步编程

异步编程

时间:2022-12-12 18:55:29浏览次数:43  
标签:异步 resolve console log 编程 value reason reject

一、Promise

1.基本用法

// Promise 基本示例
const promise = new Promise(function (resolve, reject){
    // 这里用于“兑现”承诺
    // resolve(100)
    reject(new Error('promise rejected'))
})

promise.then(function (value){
    console.log('resolved', value)
}, function (error) {
    console.log('error', error)
})

2.使用案例

// Promise 方式的 Ajax
function ajax(url) {
    return new Promise(function (resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url)
        xhr.responseType = 'json'
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}
ajax('/api/users.json').then(function (res) {
    console.log(res)
}, function (error) {
    console.log(error)
})

3.Promise链式调用

  • Promise 对象的then方法会返回一个全新的 Promise 对象

  • 后面的 then 方法就是为上一个then返回的 Promise 注册回调

  • 前面 then 方法中回调函数的返回值会作为后面then方法回调的参数

  • 如果回调中返回的是Promise,那后面的then方法的回调会等待它的结束

let promise = new Promise(resolve => {
    console.log(1)
    resolve(1)
})
promise.then((v) => {
    console.log('2: ', v)
    return 2
}).then((v) => {
    console.log('3: ', v)
})

/* 输出为:
1
2:  1
3:  2
*/

4.异常处理

let promise1 = new Promise(resolve => {
    console.log(1)
    resolve(1)
})
promise1.then((v) => {
    console.log('2: ', v)
    return 2
}).then((v) => {
    throw Error('error message')
    console.log('3: ', v)
}, err => {
    console.log(err)
})

输出是:

可以发现当此then的resolve成功函数中如果发生错误,无法被捕获,因为then中的reject失败回调只会捕获then 调用者的异常。

let promise1 = new Promise(resolve => {
    console.log(1)
    resolve(1)
})
promise1.then((v) => {
    console.log('2: ', v)
    return 2
}).then((v) => {
    throw Error('error message')
    console.log('3: ', v)
}).catch(err => {
    console.log('error message')
})

输出为:

可以发现异常被正常捕获了,所以建议Promise的链式调用中使用catch进行错误处理,catch的错误捕获可以看作是整条调用链上的错误捕获

5.Promise并行

// Promise 并行执行
function ajax(url) {
    return new Promise(function (resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url)
        xhr.responseType = 'json'
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// ajax('/api/users.json')
// ajax('/api/posts.json')

// 并行
var promise = Promise.all([
    ajax('/api/users.json'),
    ajax('/api/posts.json')
])
promise.then(function (values) {
    console.log(values)
}).catch(function (err) {
    console.log(err)
})

// 并行和串行
ajax('/api/urls.json').then(value => {
    const urls = Object.values(value)
    const tasks = urls.map(url => ajax(url))
    return Promise.all(tasks)
}).then(values => {
    console.log(values)
})

另一个并行方法是 Promise.race(),与Promise.all()的区别是:all方法是所有promise执行完成后返回结果,race是第一个promise执行完成后就返回结果

const request = ajax('/api/posts.json')
const timeout = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error('timeout')), 500)
})
Promise.race([request, timeout]).then(value => {
    console.log(11, value)
}).catch(error => console.log(error))

6.Generator生成器函数

  • 基本使用
// 比普通函数多一个*
function * foo (){
    console.log('start')
}
// 调用后不会立即执行
const r = foo()
// 执行next()方法后才会向下执行
r.next()

function * foo1 (){
    // yield后面的值,可以通过执行到这一步的next()返回值得到
    yield 'bar'
}
const r1 = foo1()
const bar = r1.next()
console.log(bar)

function * foo2 (){
    // 这里可以获取到下一步的next()中传入的值
    const res = yield 'bar'
    console.log('res: ', res)
}
const r2 = foo2()
r2.next()
r2.next('ba1')
console.log(bar)
  • 迭代器执行
// Promise 并行执行
function ajax(url) {
    return new Promise(function (resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url)
        xhr.responseType = 'json'
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

function * main() {
    try {
        const users = yield ajax('/api/users.json')
        console.log(users)
        const posts = yield ajax('/api/posts.json')
        console.log(posts)
        const users11 = yield ajax('/api/users11.json')
        console.log(users11)
    } catch (e) {
        console.log(e)
    }
}

// const result = g.next()
//
// result.value.then(data => {
//     const result2 = g.next(data)
//     if (result.done) return
//     result2.value.then(data => {
//         const result3 = g.next(data)
//         if (result3.done) return
//         result3.value.then(data => {
//             g.next(data)
//         })
//     })
// })

// 执行器
function co(generator){
    const g = generator()
    function handleResult (result) {
        if(result.done) return // 生成器函数结束
        result.value.then(data => {
            handleResult(g.next(data))
        }, error => {
            g.throw(error)
        })
    }
    handleResult(g.next())
}

co(main)

7.Async/Await 语法糖

function ajax(url) {
    return new Promise(function (resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url)
        xhr.responseType = 'json'
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

async function main() {
    try {
        const users = await ajax('/api/users.json')
        console.log(users)
        const posts = await ajax('/api/posts.json')
        console.log(posts)
        const users11 = await ajax('/api/users11.json')
        console.log(users11)
    } catch (e) {
        console.log(e)
    }
}
const promise = main()
promise.then(() => {
    console.log('complate')
})

二、手写Promise

1.Promise 核心逻辑实现

  • 分析:

1.Promise 就是一个类 在执行这个类的时候,需要传递一个执行器,执行器会立即执行

2.Promise 有三种状态:成功fulfilled、失败rejected、等待pending。

状态变化只有两种情况,且一旦确定就不可修改:

 pending -> fulfilled

 pending -> rejected

3.resolve和reject函数是用来更改状态的

 resolve: fulfilled

 reject: rejected

4.then方法内部做的事情就是判断状态,如果状态是成功,调用成功的回调函数,

如果是失败,调用失败的回调函数。then方法是定义在原型对象上的方法

5.then成功回调有一个参数,表示成功之后的值;then失败回调有一个参数,表示失败的原因

  • 实现
const PENDING = 'pending';  // 等待
const FULFILLED = 'fulfilled';  // 成功
const REJECTED = 'rejected';  // 失败
class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject)
    }
    // promise 状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败后的原因
    reason = undefined;
    resolve = value => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value
    }
    reject = reason => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason
    }
    then (successCallBack, failCallBack) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallBack(this.value)
        } else if (this.status === REJECTED) {
            failCallBack(this.reason)
        }
    }
}

module.exports = MyPromise;
  • 验证
const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    resolve('成功')
    reject('失败')
})

promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
  • 结果

2.Promise 类中加入异步逻辑

  • 场景:

如下代码所示,将resolve调用延时执行的时候,会发现没有结果输出,是因为创建时传入的执行器立即执行了,但是主程序不会等待2s后再去调用resolve方法。这时调用then方法,状态 status 的值为pending,所以没有任何输出。

const promise = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功')
    }, 2000)
})
promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
  • 修改MyPromise

在then方法中,如果状态 status 的值是pending,保存成功和失败的回调函数,等2s后执行resolve或者reject方法时,再去执行保存的回调函数。

const PENDING = 'pending';  // 等待
const FULFILLED = 'fulfilled';  // 成功
const REJECTED = 'rejected';  // 失败
class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject)
    }
    // promise 状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败后的原因
    reason = undefined;
    // 成功回调
    successCallback = undefined;
    // 失败回调
    failCallback = undefined;
    resolve = value => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value
        // 判断成功回调是否存在,如果存在就调用
        this.successCallback && this.successCallback(value)
    }
    reject = reason => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason
        // 判断失败回调是否存在,如果存在就调用
        this.failCallback && this.failCallback(reason)
    }
    then (successCallBack, failCallBack) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallBack(this.value)
        } else if (this.status === REJECTED) {
            failCallBack(this.reason)
        } else {
            // 等待状态
            // 将成功回调和失败回调保存
            this.successCallback = successCallBack;
            this.failCallback = failCallBack;
        }
    }
}

module.exports = MyPromise;

3.适配then方法被多次调用

  • 场景

如下代码所示,then方法是可以被多次调用的:

const promise = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功')
    }, 2000)
})

promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})

执行会发现只输出一个成功,因为我们保存的成功或失败回调函数只有一个,所以我们需要把之前保存回调的两个变量successCallback 和 failCallback改成数组,在赋值的时候使用push方法进行保存,最后调用的时候使用shift方法从前到后依次执行:

const PENDING = 'pending';  // 等待
const FULFILLED = 'fulfilled';  // 成功
const REJECTED = 'rejected';  // 失败
class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject)
    }
    // promise 状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];
    resolve = value => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value
        // 判断成功回调是否存在,如果存在就调用
        while (this.successCallback.length)  this.successCallback.shift()(this.value)
        // this.successCallback && this.successCallback(value)
    }
    reject = reason => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason
        // 判断失败回调是否存在,如果存在就调用
        while (this.failCallback.length)  this.failCallback.shift()(this.reason)
        // this.failCallback && this.failCallback(reason)
    }
    then (successCallBack, failCallBack) {
        // 判断状态
        if (this.status === FULFILLED) {
            successCallBack(this.value)
        } else if (this.status === REJECTED) {
            failCallBack(this.reason)
        } else {
            // 等待状态
            // 将成功回调和失败回调保存
            this.successCallback.push(successCallBack);
            this.failCallback.push(failCallBack);
        }
    }
}

module.exports = MyPromise;

4.then方法的链式调用

  • 场景:

如下代码所示,then方法是可以进行链式调用的

const promise = new myPromise((resolve, reject) => {
    resolve('成功')
})

promise.then(value => {
    console.log(value)
    return 100;
}).then(value => {
    console.log(value)
})

既然要链式调用then方法,那么then方法的返回值就必须是MyPromise对象,因为需要接收上一个then方法中成功回调函数的返回值,那么就应该接收该返回值,并且传给新建的MyPromise对象的resolve方法。then方法的代码如下所示:

	then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                let x = successCallBack(this.value)
                resolve(x)
            } else if (this.status === REJECTED) {
                failCallBack(this.reason)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(successCallBack);
                this.failCallback.push(failCallBack);
            }
        });
        return promise2;
    }

上面的处理是针对上一个then方法返回值是常量的情况,如果返回的是Promise对象呢,判断x的值是普通值,还是promise对象,修改then方法:

	then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                let x = successCallBack(this.value)
                // 判断x的值是普通值,还是promise对象
                // 如果是普通值,直接调用resolve
                // 如果是promise对象,根据promise对象返回的结果,
                // 决定调用resolve,还是调用reject
                resolvePromise(x, resolve, reject)
            } else if (this.status === REJECTED) {
                failCallBack(this.reason)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(successCallBack);
                this.failCallback.push(failCallBack);
            }
        });
        return promise2;
    }

辅助函数:

function resolvePromise(x, resolve, reject) {
    if(x instanceof MyPromise) {
        // promise对象
        // x.then(value => resolve(value), reason => reject(reason))
        // 简化
        x.then(resolve, reject)
    } else {
        // 普通值
        resolve(x)
    }
}

5.错误处理

  • 场景:

then方法中返回当前promise,发生循环调用的错误,如下代码所示:

const promise = new Promise((resolve, reject) => {
    resolve('成功')
})

let p1 = promise.then(value => {
    console.log(value)
    return p1;
})
  • 运行结果

提示发生了链式循环的错误,现在处理我们也需要处理一下,我们只需要在then方法的resolve中,判断当前promise2是否和x相同,相同就需要报错。

	then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 这里需要放在setTimeout中,是因为promise2需要等待new MyPromise执行完成后才能得到值
                setTimeout(() => {
                    let x = successCallBack(this.value)
                    // 判断x的值是普通值,还是promise对象
                    // 如果是普通值,直接调用resolve
                    // 如果是promise对象,根据promise对象返回的结果,
                    // 决定调用resolve,还是调用reject
                    resolvePromise(x, resolve, reject, promise2)
                }, 0)
            } else if (this.status === REJECTED) {
                failCallBack(this.reason)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(successCallBack);
                this.failCallback.push(failCallBack);
            }
        });
        return promise2;
    }

辅助函数中判断:

function resolvePromise(x, resolve, reject, promise2) {
    if(promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if(x instanceof MyPromise) {
        // promise对象
        // x.then(value => resolve(value), reason => reject(reason))
        // 简化
        x.then(resolve, reject)
    } else {
        // 普通值
        resolve(x)
    }
}
  • 测试:
const promise = new myPromise((resolve, reject) => {
    resolve('成功')
})

let p1 = promise.then(value => {
    console.log(value)
    return p1;
})
p1.then(value => {
    console.log(value)
}, reason => {
    console.log(reason.message)
})
  • 运行结果

6.捕获错误

  • 如果我们执行的Promise代码中有错误,应该怎么捕获呢,如下代码所示:
const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    // resolve('成功')
    throw new Error('错误')
})

promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason.message)
})

直接在构造方法中使用try...catch进行捕获即可:

	constructor(executor) {
        try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }
    }
  • 如果then的回调函数报错了,怎么处理,如下代码所示
const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    resolve('成功')
    // throw new Error('错误')
})

promise.then(value => {
    console.log(value)
    throw new Error('then 报错')
}, reason => {
    console.log(reason.message)
}).then(value => {
    console.log(value)
}, reason => {
    console.log(reason.message)
})

直接将then中的成功回调用try...catch包起来,错误时,调用下一个then的reject方法,如下代码所示:

	then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 这里需要放在setTimeout中,是因为promise2需要等待new MyPromise执行完成后才能得到值
                setTimeout(() => {
                    try {
                        let x = successCallBack(this.value)
                        // 判断x的值是普通值,还是promise对象
                        // 如果是普通值,直接调用resolve
                        // 如果是promise对象,根据promise对象返回的结果,
                        // 决定调用resolve,还是调用reject
                        resolvePromise(x, resolve, reject, promise2)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                failCallBack(this.reason)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(successCallBack);
                this.failCallback.push(failCallBack);
            }
        });
        return promise2;
    }
  • 之前只关注了then方法中返回成功分支,现在改造一下then方法的返回失败的分支:
	then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 这里需要放在setTimeout中,是因为promise2需要等待new MyPromise执行完成后才能得到值
                setTimeout(() => {
                    try {
                        let x = successCallBack(this.value)
                        // 判断x的值是普通值,还是promise对象
                        // 如果是普通值,直接调用resolve
                        // 如果是promise对象,根据promise对象返回的结果,
                        // 决定调用resolve,还是调用reject
                        resolvePromise(x, resolve, reject, promise2)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = failCallBack(this.reason)
                        resolvePromise(x, resolve, reject, promise2)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(successCallBack);
                this.failCallback.push(failCallBack);
            }
        });
        return promise2;
    }

测试代码:

const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    // resolve('成功')
    // throw new Error('错误')
    reject('失败')
})

promise.then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
    return 10000
}).then(value => {
    console.log(value)
}, reason => {
    console.log(reason.message)
})

结果:

  • 这时,then方法中就剩pending状态的代码没有进行错误捕获了,也就是异步代码部分,按照之前的方法进行改造,改造后在resolve和reject中shift后调用时也不需要传参了,所以整体代码如下所示:
const PENDING = 'pending';  // 等待
const FULFILLED = 'fulfilled';  // 成功
const REJECTED = 'rejected';  // 失败
class MyPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }
    }
    // promise 状态
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败后的原因
    reason = undefined;
    // 成功回调
    successCallback = [];
    // 失败回调
    failCallback = [];
    resolve = value => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value
        // 判断成功回调是否存在,如果存在就调用
        while (this.successCallback.length)  this.successCallback.shift()()
        // this.successCallback && this.successCallback(value)
    }
    reject = reason => {
        // 如果状态不是等待,阻止程序向下执行
        if (this.status !== PENDING) return
        // 将状态改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason
        // 判断失败回调是否存在,如果存在就调用
        while (this.failCallback.length)  this.failCallback.shift()()
        // this.failCallback && this.failCallback(reason)
    }
    then (successCallBack, failCallBack) {
        let promise2 = new MyPromise((resolve, reject) => {
            // 判断状态
            if (this.status === FULFILLED) {
                // 这里需要放在setTimeout中,是因为promise2需要等待new MyPromise执行完成后才能得到值
                setTimeout(() => {
                    try {
                        let x = successCallBack(this.value)
                        // 判断x的值是普通值,还是promise对象
                        // 如果是普通值,直接调用resolve
                        // 如果是promise对象,根据promise对象返回的结果,
                        // 决定调用resolve,还是调用reject
                        resolvePromise(x, resolve, reject, promise2)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = failCallBack(this.reason)
                        resolvePromise(x, resolve, reject, promise2)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else {
                // 等待状态
                // 将成功回调和失败回调保存
                this.successCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = successCallBack(this.value)
                            resolvePromise(x, resolve, reject, promise2)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = failCallBack(this.reason)
                            resolvePromise(x, resolve, reject, promise2)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                });
            }
        });
        return promise2;
    }
}

function resolvePromise(x, resolve, reject, promise2) {
    if(promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if(x instanceof MyPromise) {
        // promise对象
        // x.then(value => resolve(value), reason => reject(reason))
        // 简化
        x.then(resolve, reject)
    } else {
        // 普通值
        resolve(x)
    }
}

module.exports = MyPromise;

测试代码:

const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功。。。')
    },1000)
})

promise.then(value => {
    console.log(value)
    return 10000
}, reason => {
    console.log(reason)
}).then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})

测试结果:

7.then方法的参数变为可选

如下代码所示,应该是向下传递,直到找到回调函数:

const myPromise = require('./myPromise')
const promise = new myPromise((resolve, reject) => {
    resolve('成功。。。')
})

promise.then().then().then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})

在then方法的开始增加如下代码:

	then (successCallBack, failCallBack) {
        successCallBack = successCallBack ? successCallBack : value => value
        failCallBack = failCallBack ? failCallBack : reason => { throw reason }
		......
	}

8.Promise.all方法

  • 特点

    • 接收一个数组,数组中可以传入Promise对象,也可以传入普通值

    • 得到结果的顺序一定是传入的顺序

    • 返回值也是Promise对象

    • 结果都是成功,才返回成功,否则返回失败

	static all(array) {
        let result = [];
		// 此处定义index是为了统计array中的方法是否都已经执行完成(例如f1这样的异步方法)
        let index = 0
        return new MyPromise((resolve, reject) => {
            function addData (key, value) {
                result[key] = value
                index++;
                if(index === array.length) {
                    resolve(result)
                }
            }
            for (let i = 0; i < array.length; i++) {
                let current = array[i];
                if (current instanceof MyPromise) {
                    // Promise对象
                    current.then(value => addData(i, value), reason => reject(reason))
                } else {
                    // 普通值
                    addData(i, array[i])
                }
            }
        })
    }
  • 测试代码:
const myPromise = require('./myPromise')
function p1() {
    return new myPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('p1')
        }, 2000)
    })
}
function p2() {
    return new myPromise((resolve, reject) => {
        resolve('p2')
    })
}
myPromise.all(['a', 'b', p1(), p2(), 'c']).then(value => {
    console.log(value)
})
  • 测试结果:

9.promise.resolve方法

  • 功能

    • 传入普通值,返回包装后Promise对象,方便then调用

    • 传入Promise对象,返回原Promise对象

  • 实现

	static resolve (value) {
        if (value instanceof MyPromise) {
            return value
        } else {
            return new Promise(resolve => resolve(value))
        }
    }
  • 测试代码
const myPromise = require('./myPromise')
let p2 = new myPromise((resolve, reject) => {
    resolve('p2')
})
myPromise.resolve(p2).then(value => console.log(value))
myPromise.resolve(10).then(value => console.log(value))
  • 测试结果

10.finally方法

  • 功能

    • 无论成功与否,finally都会执行

    • 可以使用then方法,得到当前Promise对象返回的结果

  • 实现

	finally (callback) {
        return this.then(value => {
			// 调用resolve静态方法,是为了等待异步调用的完成
            return MyPromise.resolve(callback()).then(() => value)
        }, reason => {
            return MyPromise.resolve(callback()).then(() => {
                throw reason;
            })
        })
    }
  • 测试代码
const myPromise = require('./myPromise')

function p1() {
    return new myPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('p1')
        }, 2000)
    })
}

let p2 = new myPromise((resolve, reject) => {
    resolve('p2 resolve')
    // reject('p2 reject')
})
p2.finally(() => {
    console.log('finally')
    return p1();
}).then(value => {
    console.log(value)
}, reason => {
    console.log(reason)
})
  • 测试结果:

11.catch方法

  • 处理当前Promise的异常方法

  • 实现:

	catch (failCallback) {
        this.then(undefined, failCallback)
    }
  • 测试代码
const myPromise = require('./myPromise')
let p = new myPromise((resolve, reject) => {
    reject('p reject')
})
p.then(value => console.log(value)).catch(reason => console.log(reason))
  • 测试结果

标签:异步,resolve,console,log,编程,value,reason,reject
From: https://www.cnblogs.com/caicai521/p/16976870.html

相关文章

  • 基于Django中间件引发的编程思想
    基于Django中间件引发的编程思想(重点)importlib模块使用能够以字符串的形式导入模块,最小单位只能到模块名#1.创建一个py文件aaa.py#2.创建一个mypach文件夹,里面创......
  • 《Java并发编程详解》读书笔记
    嗯,书是假期开始看的感觉,虽然部分知识以前学过,但是在学一次巩固一下。嗯,加油生活。摘一句子,^_^有一天,突然发现自己没有热爱的东西了。就这样进入浪费时间的年代。秋天一到,候......
  • 《Python核心编程》第三版 读书笔记
    “一个不成熟男子的标志是为了某种事业英勇地死去,一个成熟男子的标志是为了某种事业卑微地活着。”                       ......
  • S02.shell图形化编程
    whiptail使用消息框语法:whiptail--title"<messageboxtitle>"--msgbox"<texttoshow>"<height><width>示例:#!/bin/bash#--title:表示指定标题内容#--msgbox:......
  • 优化-减少单个页面的异步请求次数
    场景:如果一个页面有太多的异步请求数据,即会发送很多的http请求,那么如何优化;首先没一次http请求,就会有dns解析域名-ip会耗费时间,还有http请求会消耗网络开销,即浏览器的压......
  • 系统编程之文件IO(二)——文件系统及文件描述符
    文章目录​​一、文件编程​​​​二、文件IO​​​​2.1文件IO重要性​​​​2.2根目录​​​​2.3文件描述符​​一、文件编程文件io:一切皆文件!(VFS)虚拟文件系统节省成......
  • 深度之眼(九)——python函数--面向过程的编程
    文章目录​​4.1函数的定义及调用​​​​4.1.1为什么要调用函数​​​​4.1.2函数的的定义及调用​​​​4.1.3参数传递​​​​4.1.4函数体与变量作用域​​​​4.1.......
  • 深度之眼(十三)——Python:类-面向对象的编程
    文章目录​​引子——类的引入​​​​7.1类的定义​​​​7.1.1类的命名​​​​7.1.2类的属性​​​​7.1.3类的方法​​​​7.2创建实例​​​​7.2.1实例的创建​......
  • 面向切面编程 Aop 学习笔记
    讲到java企业级开发框架,就不可避免的讲到IOC,AOP,MCV面试时被问到AOP,讲的很乱,这里整理笔记,包括AOP,spring-AOP的部分知识,错误的地方请小伙伴指出来.问题:谈谈你对AOP的理解?:AO......
  • 异步编程 async与await
    原文链接:http://t.zoukankan.com/itjeff-p-4424810.html原文链接:https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-historyC#5.0版C#版本......