当前位置: 首页 > 文档资料 > ES6 入门教程 >

承诺(Promises)

优质
小牛编辑
128浏览
2023-12-01

Promises是一种在JavaScript中实现异步编程的简洁方法(ES6新功能)。 在承诺之前,Callbacks用于实现异步编程。 让我们首先了解异步编程及其实现,使用Callbacks。

了解回调

函数可以作为参数传递给另一个函数。 这种机制被称为Callback 。 回调对事件有帮助。

以下示例将帮助我们更好地理解这一概念。

<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是“Continuation events”,它们可以帮助您以更清晰的代码风格一起执行多个异步操作。

例子 (Example)

让我们通过一个例子来理解这一点。 以下是相同的语法。

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通过使用resolve回调并传入结果返回计算结果,即n1 + n2

Step 1 - 解析(n1 + n2);

如果getSum()遇到错误或意外情况,它将调用Promise中的拒绝回调方法并将错误信息传递给调用者。

Step 2 - 拒绝(错误(“不支持否定”));

方法实现在以下代码中给出(步骤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> 

成功执行上述代码后,将显示以下输出。

程序首先显示“脚本结束”,然后逐个调用getSum()方法。

End of script  
11 
30 
70

这表明以异步样式或非阻塞样式调用getSum()。 Promise为处理回调提供了一种干净利落的方式。