相信知道ajax的人都知道异步回调是怎么一回事。在一些业务中很容易写成下面这个恶心的代码:
$.ajax({
succss:function(res){
$.ajax({
data:res.xxx
succss:function(res2){
$.ajax({
data:res2.xxx
})
}
})
}
})
哦,反正我没写过这种ajax,看起来真的挺恶心的,所以拿来举例。 但是,nodejs做后台的时候,这个情况就像下面:
{
{
{
{
{
{
{
{
}
}
}
}
}
}
}
}
唉~~~触目惊心,不仅仅阅读困难,维护起来也是要了老命啊。
不过,别忘了ES6的Promise对象,都说字如其人,Promise这家伙是名如其人,就是一承诺:这件事我去做,做成了怎么怎么样,做不成就拿人头来谢罪。下面就是用Promise对fs.readFile()的包装以及使用:
function readFile(path) {
return new Promise(function (resolve, reject) {
fs.readFile(path, (err, data) => {
if (err) {
reject(err);
}
resolve(data);
})
})
}
readFile("xxx")
.then(function(data){
...
})
.catch(function(err){
...
})
这么一来在观感上就要强很多,但自己的代码量也增加不少。好在有第三方的包替我们做了许多的工作例如 mz:
const fs=require("mz/fs");
fs.readFile("xxx")
.then(function(data){
...
})
.catch(function(err){
...
})
很舒心有没有。。。。如果觉得答案是肯定的,小伙子,还是图样图森破。慢慢的写着写着就会发现有时一堆的then这样的东西。
为了耍得更加欢快,还是用Generator:
const fs=require("mz/fs");
function * doSome(){
let a=yield fs.readfile(aaa);
let b=yield fs.readfile(bbb)
return b;
}
var f=doSome();
f.next();
f.next();
f.next();
终于 这异步写起来像同步代码了,但是需要 f.next() 方法一步一步往下执行,这样手动控制整个流程给人很不友好的感觉,好在有co库可以帮我们解决。
不过co也没快活过太久,ES7标准中 带来了异步的新语法 async/await,其实这只不过是generator的语法糖,把*换成async,把yield换成await,并且自带执行器;这么一来就在语义上显得特别友好。
const fs=require("mz/fs");
async function doSome(){
let a=await fs.readfile(aaa);
let b=await fs.readfile(bbb)
return b;
}
var f=doSome();
我仿佛看到了C#的影子、、、、、哈哈哈哈。
光说不练瞎扯淡,于是乎我把上次做的那个获取win10壁纸的代码全部用async语法改造了,先贴旧的用then语法的:
//old code
old code
const fs = require('fs');
const path = require('path');
const imageInfo = require('image-info');
/*壁纸所在的源文件夹*/
const src = path.join(process.env.localappdata, "\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\");
/*要拷贝到的文件夹:这个是在‘图片/spotlight’*/
const target = path.join(process.env.userprofile, 'Pictures\\spotlight');
/*判断spotlight文件夹是否存在*/
try {
const s = fs.statSync(target);
if (!s.isDirectory()) {
fs.mkdirSync(target);
}
} catch (error) {
fs.mkdirSync(target);
}
/*读取源文件目录下的所有文件*/
const files = fs.readdirSync(src);
files.forEach(file => {
const stats = fs.statSync(path.join(src, file));
if (stats.isFile()) {
readFile(path.join(src, file))
.then(function (data) {
/*判断文件后缀*/
const tempData = data.slice(0, 7);
let filename;
if (tempData.indexOf(Buffer.from('FFD8FF', "hex")) != -1) {
filename = path.join(target, file + ".jpg");
} else if (tempData.indexOf(Buffer.from('89504E47', 'hex')) != -1) {
filename = path.join(target, file + ".png");
}
if (filename) {
fs.writeFile(filename, data, err => {
if (err) console.log(err);
imgInfo(filename)
.then(function (data) {
/*过滤掉小文件*/
var wh = data.height / data.width;
if (wh == 1) {
fs.unlink(filename, (err) => {
if (err) {
console.log(err)
}
})
}
})
.catch(function (err) {
console.log(err);
})
});
}
})
.catch(function (err) {
console.log(err);
})
}
})
function readFile(path) {
return new Promise(function (resolve, reject) {
fs.readFile(path, (err, data) => {
if (err) {
reject(err);
}
resolve(data);
})
})
}
function imgInfo(filename) {
return new Promise(function (resolve, reject) {
imageInfo(filename, (err, info) => {
if (err) {
reject(err);
}
resolve(info);
})
})
}
下面是async改造后的:
const fs = require('mz/fs');
const path = require('path');
const imageInfo = require('image-info');
/*壁纸所在的源文件夹*/
const src = path.join(process.env.localappdata, "\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\");
/*要拷贝到的文件夹:这个是在‘图片/spotlight’*/
const target = path.join(process.env.userprofile, 'Pictures\\spotlight');
start();
async function start() {
await checkdir();
await copyFile();
}
/*判断spotlight文件夹是否存在*/
async function checkdir() {
try {
const s = await fs.stat(target);
if (!s.isDirectory()) {
await fs.mkdir(target);
}
} catch (error) {
await fs.mkdir(target);
}
}
/*读取源文件目录下的所有文件*/
async function copyFile() {
const files = await fs.readdir(src);
files.forEach(async (file) => {
const stats = await fs.stat(path.join(src, file));
if (stats.isFile()) {
const data = await fs.readFile(path.join(src, file));
const tempData = data.slice(0, 7);
let filename;
if (tempData.indexOf(Buffer.from('FFD8FF', "hex")) != -1) {
filename = path.join(target, file + ".jpg");
} else if (tempData.indexOf(Buffer.from('89504E47', 'hex')) != -1) {
filename = path.join(target, file + ".png");
}
if (filename) {
await fs.writeFile(filename, data);
const info = await imgInfo(filename);
var wh = info.height / info.width;
if (wh == 1) {
await fs.unlink(filename);
}
}
}
});
}
function imgInfo(filename) {
return new Promise(function (resolve, reject) {
imageInfo(filename, (err, info) => {
if (err) {
reject(err);
}
resolve(info);
})
})
}
没有对比就没有伤害啊。
其实我就是说说async好,不存在任何语法上的教程。如果想了解或者深入了解相关知识,很明显你需要这个ES6入门教程; 建议多学习一些基本语法,算法,设计模式相关的知识。要知其然还要知其所以然。
这里是‘获取win10壁纸’的项目原址:win10spotlight