JavaScript/Node.js异步函数的发展历史和基本使用
2018-06-28 本文已影响24人
小小奶狗
NodeJS学习咯
远古的ES5时代,让我们来简单模拟一下远古时代使用 chunk
回调函数处理异步时候,我们怎么操作 MongoDB
数据库:
mongoDb.open(function(err, db){
if(!err){
db.collection("users", function(err, collection){
if(!err){
let person = {name: "yika", age: 20};
collection.insert(person, function(err, result){
if(!err){
console.log(result);
}
});
}
})
}
});
这就是被我们所诟病的回调地狱(
callback hell
),一堆横向金字塔,如果将回调拆分成函数,则会变得非常支离破碎。为了防止到恶心到大家,我甚至没有写关于错误的处理,正常来说,每一个异步的操作都需要都它的error
进行相应的显示或处理的。
时间来到了 ECMAScript2015
也就是ES6语法啦。ES6中提供了两种方案解决回调地狱:Promise和Generator。我们先来对比一下两者改写上面 mongoDB
插入数据的代码。(ES6同时提供的箭头函数也在这里试用一下)
let person = {name: "yika"};
mongoDb.open()
.then(database => {
return database.collection("users");
})
.then(collection => {
return collection.insert(person);
})
.then(result => {
console.log(result);
})
.catch(e => {
throw new Error(e);
})
let co = require("co");
co(function *(){
let db, collection, result;
let person = {name: "yika"};
try{
db = yield mongoDb.open();
collection = yield db.collection("users");
result = yield collection.insert(person);
}catch(e){
console.error(e.message);
}
console.log(result);
});
是不是发现了明显的不同,
Promise
的写法还是存在嵌套,只不过看起来用链式调用掩盖了嵌套罢了,但起码chuck
函数变成了promise
函数,原本一层层包裹的金字塔变成了楼梯;而Generator
迭代器则是利用 co 启动器模块, * 符和 yield 关键字,近乎真正的实现了异步代码风格同步化(仍有外层一次异步)。可是你有没有发现,这特么很不语义化啊,鬼知道 * 符和 yield 是干嘛用的,别急接着看。
在2017年末时候 ECMAScript2017
也就是ES8中处理异步的方案加了个 async await
,这也是当时
NodeJS7.x
中提出来的,实际上就是 generator
的语法糖,改造一下更健康,更语义化。代码如下:
async function insertData(person){
let db, collection, result;
try{
db = await mongoDb.open();
collection = await db.collection("users");
result = await collection.insert(person);
}catch(e){
console.error(e.message);
}
console.log(result);
}
insertData({name: "yika"});
是不是发现这变成了
PHP,JAVA,C/C++
的同步编程风格,哈哈哈哈是的async就是这么强,而且目前这个模块已经加入 NodeJS 的内建模块中,使用前只需要引入util.promisify
即可。在Node真实项目中建议对controller
层进行一级分层,专门建立util
目录存放各模块中使用到的异步函数(同步写法),控制器中引入并调用函数即可。
既然async这么牛逼,我们具体怎么使用它呢?Server端的Node使用就不用多说了,内建模块。直接看Brower端吧,如果你使用了Webpack,那么只需要这样配置babel解析器即可:
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel",
query: {
presets: ['es2015', 'stage-3']
}
},
]
}