诺言一直是解决JavaScript "回调地狱 "问题的主要方法,但从ES6开始,现在ES7正在慢慢地将其隐藏起来,为async 和await 。
目前,"回调地狱 "可以通过使用诸如async之类的库来缓解,或者通过使用由koa推广的生成器来缓解。但这两种方法都属于黑客/助手的范畴,只是掩盖了基本问题。
有了ES7,我们将能够以一种不那么黑的方式来编写我们的异步代码,就像它是同步的一样。
异步
下面是一个异步代码的例子。
async function run(){
if(Math.round(Math.random())){
return 'Success!';
} else {
throw 'Failure!';
}
}
async 关键字允许我们使用await ,它保证了该函数将返回一个Promise ,其状态是已解决或已拒绝。当你从一个异步函数返回时,你将返回一个带有解析值的Promise 对象。要拒绝,就抛出一个错误,这将返回一个错误对象。
上面的代码块本质上与之相同。
function run(){
if(Math.round(Math.random())){
return Promise.resolve('Success!');
}else{
return Promise.reject('Failure!');
}
}
我们可以采取任何函数,并通过添加async 关键字使其返回一个Promise 对象。下面是一个例子。
async function get(value){
return value + 10;
}
Await
现在,await关键字。
在异步函数内部时,可以用await 关键字添加承诺返回的表达式。通过这样做,它将暂停函数的其余部分的执行,直到返回的承诺被解决或拒绝。请看这个简单的例子。
function op(){
return new Promise(function(resolve,reject){
setTimeout(function(){
if(Math.round(Math.random())){
resolve('Success')
}else{
reject('Fail')
}
},2000)
});
}
async function foo(){
console.log('running')
try {
var message = await op();
console.log(message)
} catch(e) {
console.log('Failed!', e);
}
}
foo()
当你调用foo() ,它将等待2000毫秒,然后要么解决要么拒绝。注意这个try/get。现在我们可以捕捉错误了。
结论
总之,这是解决 "回调地狱 "的最好方法,没有不可捕捉的承诺错误和生成器黑客。ES7仍在开发中,但通过babel或traceur,今天就可以使用它了。