对于复杂的异步执行任务可能会嵌套很多层回调函数,这样编写不够“优雅”,要是用同步方式编写异步代码的解决方案实质上只是改变了代码编写方式,简化和优化代码的写法,使开发人员以更优雅的方式编写异步代码,以解决异步代码的流程控制问题,降低了异步编程难度。但程序本质上还是异步执行的,这些方案并没有对程序本身进行优化,也没有提高应用程序性能。
Promise对象代表一个异步操作,有以下3种状态:等待(Pending):初始状态,没有实现也没有被拒绝;实现(Fulfilled):操作已成功完成; 被拒绝(Rejected):操作失败。简化回调嵌套只是Promise的一项基本功能,Promise最关键的是状态,Promise通过维护和传递状态的方式使回调函数能够及时被调用,这比直接传递回调函数要简单和灵活得多。
//-----------1.Promise异步操作对象--------------
//异步操作=》promise对象化
let promise = new Promise((resolve,reject)=>{
let excuteRes = true;
console.log("异步操作执行代码模拟...");
if(excuteRes)
{
resolve("执行成功");
}else
{
reject("执行失败");
}
});
promise.then((value)=>{
console.log(value);
});
promise.catch((error)=>{
console.error(error);
});
【运行结果】
Generator是一个生成器,同时也是一个状态机,其内部拥有值和相关状态。生成器返回一个迭代器(Iterator)对象,可以编写程序通过该对象遍历相关的值和状态,以保证正确的执行顺序。Generator本质上是一个函数,其最大的特点是可以被中断,然后再恢复执行。Promise对象创建之后,就会处于等待状态并开始执行,直到状态改变之后才能进行下一步操作。Generator函数可以由用户执行中断,去执行其他操作,然后从中断处恢复执行。
//-------------Generator函数【迭代器】------
function* genFunc(index)
{
yield index+1;
yield index+3;
yield index+5;
return index+7;
yield index + 9;
}
let gen = genFunc(0);
console.log("索引值:"+util.inspect(gen.next()));
console.log("索引值:"+util.inspect(gen.next()));
console.log("索引值:"+util.inspect(gen.next()));
console.log("索引值:"+util.inspect(gen.next()));
console.log("索引值:"+util.inspect(gen.next()));
【运行结果】
co模块将Generator函数包装成一个Promise对象,作为参数传递给co()方法,在co()方法内部自动执行yield,以将异步操作改为“顺序”执行。co()方法包括一个Generator函数,co()方法在Generator函数中使用yield指向Promise对象,通过递归调用next()方法将每一个Promise的值返回,从而实现异步转“同步”的代码编写方式。 co()方法返回一个Promise对象,可以调用then()和catch()方法对Generator函数返回的结果进行传递,以方便后续的成功处理或者错误处理。
const co = require("co");
//---------2.Promise对象和Generator函数结合,形成co模块,用于方便编写复杂的异步操作代码
co(function* (){
let promise1 = yield new Promise((resolve,reject)=>{
console.log("promise1 执行");
let excRes = true;
if(excRes)
{
resolve("执行成功");
}else
{
reject("执行失败");
}
});
return promise1;
})
.then((value)=>{
console.log(value);
},(error)=>{
console.error(error);
});
【运行结果】
async/await基于协程(Coroutine)的机制,是对异步过程更精确的一种描述。async/await是对Promise的改进。只是语法糖,本质上仍然是Promise。同步代码和异步代码可以一起编写,只是要注意异步过程需要包装成一个Promise对象并置于await关键字后面。
//-------3.使用async和await关键字----------
function waitMethod()
{
let promise = new Promise((resolve,reject)=>{
let excRes = true;
console.log("异步执行操作模拟");
if(excRes)
{
resolve("异步操作执行成功");
}else
{
reject("异步操作失败");
}
});
return promise;
}
//异步函数,这里可以有多个await函数表达式
async function asyncMethod()
{
var wait1 = await waitMethod();
return wait1;
}
//调用async异步函数
asyncMethod().then((value)=>{
console.log(value);
}).catch((err)=>{
console.error(err);
});
【运行结果】
异步编程方式,一般针对复杂的异步执行任务时考虑使用,简化回调,变成“同步串行”编码方式。