- 0133技术站
- 联系QQ:18840023
- QQ交流群
- 微信公众号
Promise是一种在JavaScript中实现异步编程的简洁方法(ES6新功能)。在Promise之前,使用Callbacks实现异步编程。让我们首先了解异步编程及其使用Callbacks实现。
了解Callbacks
函数可以作为参数传递给另一个函数。这种机制被称为Callbacks(回调)。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通过引入Promise的概念来帮助您。Promise是“延续事件”,它们可以帮助您以更清晰的代码风格一起执行多个异步操作。
例
让我们通过一个例子来理解这一点。以下是语法:
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
实现Promise的第一步是创建一个使用Promise的方法。在这个例子中,假设getSum()方法是异步的,即它的操作不应该阻止其他方法的执行。一旦此操作完成,它将在稍后通知调用方。
以下示例(步骤1)声明了Promise对象'var promise'。Promise构造函数首先处理函数,以便成功完成工作,然后在发生错误时获取另一个函数。
promise通过使用resolve回调函数返回计算结果并传递结果,即,n1 + n2。
步骤1 - resolve(n1 + n2);
如果getSum()遇到错误或意外情况,它将调用Promise中的拒绝回调方法并将错误信息传递给调用者。
步骤2 - 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语句。第一个“then”将有一个return语句。
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>
成功执行上述代码时将显示以下输出:
程序首先显示“end of script”,然后逐个调用getSum()方法得出结果。
End of script 11 30 70
这显示getSum()是以异步样式或非阻塞样式调用的。Promise提供了一种很好的、干净的方法来处理回调。
推荐手册