本帖最后由 大蓝鲸小蟀锅 于 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)
})
|
|