A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 大蓝鲸小蟀锅 于 2020-4-17 16:55 编辑

(1)为什么会有同步和异步

    因为JavaScript的单线程,因此同个时间只能处理同个任务,所有任务都需要排队,前一个任务执行完,才能继续执行下一个任务,但是,如果前一个任务的执行时间很长,比如文件的读取操作或ajax操作,后一个任务就不得不等着,拿ajax来说,当用户向后台获取大量的数据时,不得不等到所有数据都获取完毕才能进行下一步操作,用户只能在那里干等着,严重影响用户体验

    因此,JavaScript在设计的时候,就已经考虑到这个问题,主线程可以完全不用等待文件的读取完毕或ajax的加载成功,可以先挂起处于等待中的任务,先运行排在后面的任务,等到文件的读取或ajax有了结果后,再回过头执行挂起的任务,因此,任务就可以分为同步任务和异步任务

(2)同步任务

    同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务

(3)异步任务

    异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务
    总结:   同步是 上面的代码块执行完 在执行下面的代码块
            异步是: 当发现有异步操作  会把异步代码丢到任务队列。等到主线程代码执行完毕之后再去执行 任务队列的代码
    node中的读取:
        readFile读取
        readFile(参数1,参数2,参数3)
        参数1: 要读取文件的路径。
        参数2:要读取文件的编码格式。
        参数3:读取成功或者失败的回调函数
            参数1: 读取的错误信息
            参数2: 成功的内容
    问题1: 如何实现依次读取?
fs.readFile("1.txt", "utf8", function (err, data) {
    if (err) throw err;
    console.log(data)
    fs.readFile("2.txt", "utf8", function (err, data) {
        if (err) throw err;
        console.log(data)
        fs.readFile("3.txt", "utf8", function (err, data) {
            if (err) throw err;
            console.log(data)
        })
    })
})
会引起恶魔金字塔(回调地狱)。
###promise是什么?
    1.字面意义: 承诺  本质 承诺将来会执行
    2.主要解决回调地狱问题
    3.Promise是异步解决方案
    4.Promise是一个构造函数 函数里面有一些属性和方法(使用通过new)
###Promise的基本用法:
let p = new Promise(function (resolve, reject) {
    成功的状态
    resolve("success")
    失败的状态
    reject("error")
})
p.then(function (data) {
    console.log(data)
}, function (err) {
    console.log(err)
})
###promise的注意事项:
    1.Promise是一个构造函数  里面有两个参数  resolve成功的状态  reject代表失败的状态
    2.then里面的回调函数的结果就是上面resolve和reject的参数内容
    3.两者要么是成功的状态 要么是失败的状态  只能执行其中的一个
    4.当Promise执行错误的时候下一个then会执行成功的方法。
###promise的源码操作?
####构造函数的成功或者失败的模拟
function Promise(executor) {
    // 正在进行
    this.status = "pending"
    // 成功的值
    this.success = undefined;
    // 失败的值
    this.error = undefined;
    // 想法:等到1秒之后再一起执行?
    // 定义成功的数组
    this.onfufilledCallback = [];
    // 定义失败的数组
    this.onrejectedCallback = [];
    let that = this;
    // 成功的函数
    function resolve(val) {
        if (that.status == "pending") {
            that.status = "fufilled";
            that.success = val;
            // 如何执行 数组里面的函数?
            // 当函数调用的时候去执行数组的面的函数
            that.onfufilledCallback.forEach(fn => fn())
        }
    }
    // 失败的函数
    function reject(val) {
        if (that.status == "pending") {
            that.status = "rejected";
            that.error = val;
            // 执行失败的数组
            that.onrejectedCallback.forEach(fn => fn())
        }
    }
    捕获错误
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

####原型的then方法:
Promise.prototype.then = function (onfufilled, onrejected) {
    let that = this;
    let promise2 = new Promise(function (resolve, reject) {
        // 上面是成功的状态
        if (that.status == "fufilled") {
            try {
                let res = onfufilled(that.success)
                resolve(res)
            } catch (e) {
                reject(e)
            }
        }
        if (that.status == "rejected") {
            try {
                let res = onrejected(that.error)
                resolve(res)
            } catch (e) {
                reject(e)
            }
        }
        // 说明没有走成功和失败
        if (that.status == "pending") {
            that.onfufilledCallback.push(function () {
                try {
                    let res = onfufilled(that.success)
                    resolve(res)
                } catch (e) {
                    reject(e)
                }
            });
            that.onrejectedCallback.push(function () {
                try {
                    let res = onrejected(that.error)
                    resolve(res)
                } catch (e) {
                    reject(e)
                }
            })
        }
    })
    return promise2;
}

###catch是then的另一种写法错误信息:
// 定义catch 错误信息  其实catch就是then的另一种写法
Promise.prototype.catch = function (callback) {
    // 其实就是执行then的错误信息
    return this.then(function () { }, callback)
}
####all方法依次读取内容
// all  数组的形式  那么数组里面的内容依次来执行
// 因此 数组的内容可以是promise  也可以是具体点得数值
注意:返回的是数组
Promise.all = function (values) {
    return new Promise(function (resolve, reject) {
        let num = 0;
        let arr = [];
        function Process(key, value) {
            // 把值存储在是数组里面
            arr[key] = value;
            if (++num == values.length) {
                说明数组里面的内容执行完毕
                resolve(arr)
            }
        }
        for (let i = 0; i < values.length; i++) {
            let current = values;
            if (current.then && typeof current.then == "function") {
                // 此时是promise对象
                // 当前的this 呼叫current调用
                current.then.call(current, function (val) {
                    Process(i, val)
                }, reject)
            } else {
                // 说明是具体的值
                Process(i, current)
            }
        }
    })
}


###利用promise来读取按需加载:
const fs = require("fs");
function Read(url) {
    return new Promise(function (resolve, reject) {
        fs.readFile(url, "utf8", function (err, data) {
            if (err) reject(err);
            resolve(data)
        })
    })
}
Read("files/1.txt").then(function (data) {
    console.log(data)
    return Read("files/2.txt")
}).then(function (data) {
    console.log(data)
    return Read("files/3.txt")
}).then(function (data) {
    console.log(data)
})


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马