ES6-18/19 异步的开端-promise

ES6-18异步的开端-promise
ES6-19 promise的使用方法和自定义promisify

  • try catch只能捕获同步异常,不能捕获异步的
    在这里插入图片描述
  • 等待所有异步都执行完,打印结果,比较笨拙的方法,在每个异步操作加arr.length === 3 && show(arr)

Promise是构造函数

  • 原型上的方法then、catch、finally

  • 其余都在构造函数上:all、race、reject、resolve
    在这里插入图片描述

  • 实例化的参数executor是一个函数

  • executor里的代码是同步的

  • executor接收2个参数resolve、reject,这2个回调函数是异步的

  • 执行顺序同步>resolve(异步微任务)>setTimeout(异步宏任务)

Promise对象实现的 Ajax

const getJSON = function (url) {
    const promise = new Promise(function (resolve, reject) {
        const handler = function () {
            console.log('client实例', this)
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.status));
            }
        };
        const client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
    });

    return promise;
};

getJSON("/posts.json").then(function (json) {
    console.log('Contents: ' + json);
}, function (error) {
    console.log('请求状态码', error); // 请求状态码 Error: 404
});

在这里插入图片描述

链式调用

  • 每次.then返回的是一个新的Promise实例,在下一个.then接收

返回值是Promise时

const p1 = new Promise(function (resolve, reject) {
    console.log('p1', new Date()) // p1 Sun Jul 25 2021 15:33:01 GMT+0800 (台北标准时间)
    setTimeout(() => {
        console.log('10s后p1-resolved', new Date()) // 10s后p1-resolved Sun Jul 25 2021 15:33:11 GMT+0800 (台北标准时间)
        reject(new Error('fail'))
    }, 10000)
})

const p2 = new Promise(function (resolve, reject) {
    console.log('p2', new Date()) // p1 Sun Jul 25 2021 15:33:01 GMT+0800 (台北标准时间)
    setTimeout(() => {
        console.log('1s后p2-resolved', new Date(), p1) // 1s后p2-resolved Sun Jul 25 2021 15:33:02 GMT+0800 (台北标准时间)
        resolve(p1)
    }, 1000)
})

p2
    .then(result => console.log(result))
    .catch(error => console.log('err', error)) // err Error: fail

异步代码

  • 分为宏任务(宏任务队列)、微任务(微任务队列)
  • 除了resolve、reject和node的process.nextTick是微任务,其他是宏任务?
  • 事件循环、轮询
const { log } = console
// 一开始的微任务队列 q1
Promise.resolve().then(() => {
    log('promise1')
    setTimeout(() => { // 进入q2
        log('st2')
    })
})
// 一开始的宏任务队列 q2
setTimeout(() => {
    log('st1')
    Promise.resolve().then(() => {
        log('promise2')
    })
})
// promise1
// st1
// promise2
// st2

executor报错

  • 会吃掉状态固化以后,executor代码的错误
const p = new Promise((resolve, reject) => {
    resolve(1)
    console.log(a) // 报错 但是外部不体现
})
p.then((data) => {
    console.log(data)//1
})
new Promise((resolve, reject) => {
    resolve(2);
    console.log('P2同步');
}).then(r => {
    console.log(r);//2
});
// P2同步
// 1
// 2
const p = new Promise((resolve, reject) => {
    resolve(a) // 这样报错外部就会体现了
    // ReferenceError: a is not defined
})
p.then((data) => {
    console.log(data)
})

构造器上方法

  • 参数是有iterator接口的数据结构

all

  • 都成功,返回都成功的结果,在.then里能拿到这个数组
  • 若有一出错,在.catch里拿到第一个失败的?

race

  • 无论成功还是失败,返回第一个成功or失败的Promise

thenable

let obj = {
    then: function (resolve, reject) {
        resolve(1)
    }
}
let p = Promise.resolve(obj) // 转成promise对象
p.then((val) => {
    console.log(val) // 1
})

// reject怎么做

promisify

  • 手写promisify
const fs = require('fs')
function readFile(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf-8', (err, data) => {
            if (err) {
                reject(new Error(err))
            } else {
                resolve(data)
            }
        })
    })
}
readFile('first.txt').then((data) => {
    return readFile(data)
}).then((data) => {
    return readFile(data)
}).then((data) => {
    console.log(data)
})
  • 使用node提供的工具类方法
const fs = require('fs')
function promisify(func) {
    return function (...args) {
        return new Promise((resolve, reject) => {
            func(...args, (err, data) => {
                if (err) {
                    reject(new Error(err))
                } else {
                    resolve(data)
                }
            })
        })
    }
}
let readFile = promisify(fs.readFile)
readFile('first.txt', 'utf-8')
.then(data =>readFile(data, 'utf-8'))
.then(data =>readFile(data, 'utf-8'))
.then(data => console.log(data))
const fs = require('fs')
const util = require('util')
let readFile = util.promisify(fs.readFile)
readFile('first.txt', 'utf-8')
.then(data =>readFile(data, 'utf-8'))
.then(data =>readFile(data, 'utf-8'))
.then(data => console.log(data))
  • 将fs上的所有方法都promisify
function promisifyAll(obj) {
    for (let [key, fn] of Object.entries(obj)) {
        if (typeof fn === 'function') {
            obj[key + 'Async'] = promisify(fn)
        }
    }
}
promisifyAll(fs)
function promisify(func) {
    return function (...args) {
        return new Promise((resolve, reject) => {
            func(...args, (err, data) => {
                if (err) {
                    reject(new Error(err))
                } else {
                    resolve(data)
                }
            })
        })
    }
}
let readFile = fs.readFileAsync
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值