ES6 Promise
Promise是一种实现JavaScript的异步编程的干净的方式。
在Promise之前,Callbacks被用来实现异步编程。让我们从使用回调了解什么是异步编程及其实现开始。
了解回调
函数可以作为参数传递给另一个函数。这种机制被称为回调。回拨将有助于事件。
下面的例子将帮助我们更好地理解这个概念。
<script>
function notifyAll(fnSms, fnEmail) {
console.log('starting notification process');
fnSms();
fnEmail();
}
notifyAll(function() {
console.log("Sms send ..");
},
function() {
console.log("email send ..");
});
console.log("End of script");
//executes last or blocked by other methods
</script>
在上面显示的notifyAll()方法中,通知通过发送SMS和发送电子邮件发生。因此,notifyAll方法的调用者必须传递两个函数作为参数。每个功能都负责发送短信和发送电子邮件等单个职责。
在成功执行上述代码时,会显示以下输出。
starting notification process Sms send .. Email send .. End of script
在上面提到的代码中,函数调用是同步的。这意味着UI线程将等待完成整个通知过程。同步呼叫成为阻塞呼叫。现在让我们了解非阻塞或异步呼叫。
了解AsyncCallback
考虑上面的例子。
要启用该脚本,请对notifyAll()方法执行异步调用或非阻塞调用。我们将使用JavaScript的setTimeout()方法。此方法默认为异步。
setTimeout()方法有两个参数:
- 回调函数。
- 该方法将被调用的秒数。
在这种情况下,通知过程已被超时包装。因此,这将需要两秒钟的延迟,由代码设置。notifyAll()将被调用,并且主线程像执行其他方法一样继续。因此,通知过程不会阻塞主JavaScript线程。
<script>
function notifyAll(fnSms, fnEmail) {
setTimeout(function() {
console.log('starting notification process');
fnSms();
fnEmail();
}, 2000);
}
notifyAll(function() {
console.log("Sms send ..");
},
function() {
console.log("email send ..");
});
console.log("End of script"); //executes first or not blocked by others
</script>
在成功执行上述代码时,会显示以下输出。
End of script starting notification process Sms send .. Email send ..
在多次回调的情况下,代码看起来很可怕。
<script>
setTimeout(function() {
console.log("one");
setTimeout(function() {
console.log("two");
setTimeout(function() {
console.log("three");
}, 1000);
}, 1000);
}, 1000);
</script>
通过引入承诺的概念,ES6为您解救。承诺是“延续事件”,它们帮助您以更简洁的代码风格一起执行多个异步操作。
实例
让我们以一个例子来理解这一点。以下是相同的语法。
var promise = new Promise(function(resolve , reject) {
// do a thing, possibly async , then..
if(/*everthing turned out fine */) resolve("stuff worked");
else
reject(Error("It broke"));
});
return promise;
// Give this to someone
实现承诺的第一步是创建一个使用承诺的方法。比方说,在这个例子中,getSum()方法是异步的,即它的操作不应该阻塞其他方法的执行。此操作一旦完成,它将稍后通知呼叫者。
以下示例(步骤1)声明Promise对象'var promise'。Promise构造函数首先为函数的成功完成而提供函数,另一个函数则在发生错误时进行。
该promise通过使用解析回调并传递结果返回计算结果,即n1 + n2
第1步 - resolve(n1 + n2);
如果getSum()遇到错误或意外情况,它将调用Promise中的reject回调方法,并将错误信息传递给调用者。
第二步 - reject(Error("Negatives not supported"));
方法的实现在下面的代码中给出(步骤1)。
function getSum(n1, n2) {
varisAnyNegative = function() {
return n1 < 0 || n2 < 0;
}
var promise = new Promise(function(resolve, reject) {
if (isAnyNegative()) {
reject(Error("Negatives not supported"));
}
resolve(n1 + n2)
});
return promise;
}
第二步详述呼叫者的实施(步骤2)。
调用者应该使用'then'方法,该方法采用两种回调方法 - 第一种是成功,第二种是失败。每种方法都有一个参数,如下面的代码所示。
getSum(5, 6)
.then(function (result) {
console.log(result);
},
function (error) {
console.log(error);
});
在成功执行上述代码时,会显示以下输出。
11
由于getSum()的返回类型是一个Promise,我们实际上可以有多个'then'语句。第一个'那么'将有一个返回声明。
getSum(5, 6)
.then(function(result) {
console.log(result);
returngetSum(10, 20);
// this returns another promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
},
function(error) {
console.log(error);
});
在成功执行上述代码时,会显示以下输出。
11 30
以下示例使用getSum()方法发出三个then()调用。
<script>
function getSum(n1, n2) {
varisAnyNegative = function() {
return n1 < 0 || n2 < 0;
}
var promise = new Promise(function(resolve, reject) {
if (isAnyNegative()) {
reject(Error("Negatives not supported"));
}
resolve(n1 + n2);
});
return promise;
}
getSum(5, 6)
.then(function(result) {
console.log(result);
returngetSum(10, 20);
//this returns another Promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
returngetSum(30, 40);
//this returns another Promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
},
function(error) {
console.log(error);
});
console.log("End of script ");
</script>
在成功执行上述代码时,会显示以下输出。
该程序首先显示“脚本结束”,然后逐个调用getSum()方法。
End of script 11 30 70
这显示getSum()以异步样式或非阻塞样式调用。Promise给出了一个很好和干净的方式来处理回调。
下一章:ES6 模块
ES6通过模块的概念来解决JavaScript代码需要重用的场景。一个模块只不过是一个写在文件中的JavaScript代码块。模块中的函数或变量不可用,除非模块文件导出它们。简单地说,这些模块可以帮助你在你的模块中编写代码,并 ...
AI 中文社