为什么要写成同步
nodejs是单线程的,为了避免阻塞,在进行io操作的时候为了就采用异步执行的方式.但是很多时候异步执行会带来很多麻烦,比如我们读文件,拿到文件数据再进行操作,这个时候如果异步那么就会打不到想要的效果
那么就有了把异步改成同步的方法,在js的发展历程中一共出现了四种异步改成同步的方式
方式一:回调函数
const fs = require("fs")
//第一阶段,回调函数
function readFile(cb){
fs.readFile('./package.json',(err,data)=>{
if(err){
return cb(err)
}else{
cb(null,data)
}
})
}
readFile((err,data)=>{
if(!err){
data = JSON.parse(data)
console.log(data)
}else{
console.log("failed")
}
})
方式二:Promise
function readFileAsync(path){
return new Promise((resolve,reject)=>{
fs.readFile(path,(err,data)=>{
if(err) reject(err)
else resolve(data)
})
})
}
readFileAsync('./package.json')
.then(data => {
data =JSON.parse(data)
console.log(data)
})
.catch(err => {
console.log(err)
})
方式三:co+生成器+util
const co = require("co")
const util = require('util')
co(function *(){
let data = yield util.promisify(fs.readFile)('./package.json')
data = JSON.parse(data)
console.log(data)
})
方式四:Async
const readAsync = util.promisify(fs.readFile)
async function init(){
let data = await readAsync('./package,json')
data = JSON.parse(data)
console.log(data)
}
几个关于异步的题目
1.
var p = new Promise((resolve, reject) => {
resolve(3) // 这里是一定会异步操作
})
p.then(v => console.log(v,'1'))
p.then(v => console.log(v,'2'))
p.then(v => console.log(v,'3'))
console.log(4)
首先promise类型都是放入队列的,遇到io操作,promise都放入队列,所以先打印4,再以此打印1,2,3
2.
console.log(1)
const p = new Promise((resolve, reject) => {
console.log(2)
setTimeout(() => console.log(3), 0)
resolve(4)
})
p.then(v => console.log(v))
console.log(5)
先打印1
再打印2
遇到settimeout放入别的线程
promis进入队列
打印5
打印promise
打印settimeout
所以答案是1.2.5.4.3
这里有一个问题,就是为什么timeout设置的是0但是确实最后执行的?公司的师兄给我的解释是这在一个单独的现场里,所以什么时候运行不可预期,一般来说在一个for循环里的settimeout都是最后执行.