为什么要写成同步
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都是最后执行.