- ES6 教程
- ES6 - 主页
- ES6 - 概述
- ES6 - 环境
- ES6 - 语法
- ES6 - 变量
- ES6 - 运算符
- ES6 - 决策
- ES6 - 循环
- ES6 - 函数
- ES6 - 事件
- ES6 - Cookie
- ES6 - 页面重定向
- ES6 - 对话框
- ES6 - 无效关键字
- ES6 - 页面打印
- ES6 - 对象
- ES6 - 数字
- ES6 - 布尔值
- ES6 - 字符串
- ES6 - 符号
- ES6 - 新的字符串方法
- ES6 - 数组
- ES6 - 日期
- ES6 - 数学
- ES6 - 正则表达式
- ES6 - HTML DOM
- ES6 - 迭代器
- ES6 - 集合
- ES6 - 类
- ES6 - 地图和集合
- ES6 - 承诺
- ES6 - 模块
- ES6 - 错误处理
- ES6 - 对象扩展
- ES6 - 反射 API
- ES6 - 代理 API
- ES6 - 验证
- ES6 - 动画
- ES6 - 多媒体
- ES6 - 调试
- ES6 - 图像映射
- ES6 - 浏览器
- ES7 - 新特性
- ES8 - 新特性
- ES9 - 新特性
- ES6 有用资源
- ES6 - 快速指南
- ES6 - 有用的资源
- ES6 - 讨论
ES6 - 承诺
Promise 语法
下面提到promise相关的语法,其中p是promise对象,resolve是promise执行成功时应该调用的函数,reject是promise遇到错误时应该调用的函数。
let p = new Promise(function(resolve,reject){ let workDone = true; // some time consuming work if(workDone){ //invoke resolve function passed resolve('success promise completed') } else{ reject('ERROR , work could not be completed') } })
例子
下面给出的示例显示了一个函数add_positivenos_async(),它异步添加两个数字。如果传递正值,则承诺得到解决。如果传递负值,则承诺将被拒绝。
<script> function add_positivenos_async(n1, n2) { let p = new Promise(function (resolve, reject) { if (n1 >= 0 && n2 >= 0) { //do some complex time consuming work resolve(n1 + n2) } else reject('NOT_Postive_Number_Passed') }) return p; } add_positivenos_async(10, 20) .then(successHandler) // if promise resolved .catch(errorHandler);// if promise rejected add_positivenos_async(-10, -20) .then(successHandler) // if promise resolved .catch(errorHandler);// if promise rejected function errorHandler(err) { console.log('Handling error', err) } function successHandler(result) { console.log('Handling success', result) } console.log('end') </script>
上述代码的输出如下 -
end Handling success 30 Handling error NOT_Postive_Number_Passed
承诺链
当我们需要一个接一个地完成一系列异步任务时,可以使用Promise 链。当一个承诺依赖于另一个承诺的结果时,承诺就被链接起来。如下例所示
例子
在下面的示例中,add_positivenos_async() 函数异步添加两个数字,如果传递负值则拒绝。当前异步函数调用的结果作为参数传递给后续函数调用。请注意,每个then()方法都有一个 return 语句。
<script> function add_positivenos_async(n1, n2) { let p = new Promise(function (resolve, reject) { if (n1 >= 0 && n2 >= 0) { //do some complex time consuming work resolve(n1 + n2) } else reject('NOT_Postive_Number_Passed') }) return p; } add_positivenos_async(10,20) .then(function(result){ console.log("first result",result) return add_positivenos_async(result,result) }).then(function(result){ console.log("second result",result) return add_positivenos_async(result,result) }).then(function(result){ console.log("third result",result) }) console.log('end') </script>
上述代码的输出如下 -
end first result 30 second result 60 third result 120
下面详细讨论 Promise 对象的一些常用方法 -
承诺.all()
此方法对于聚合多个 Promise 的结果非常有用。
句法
下面提到了promise.all()方法的语法,其中iterable是一个可迭代对象。例如数组。
Promise.all(iterable);
例子
下面给出的示例执行异步操作数组[add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]。当所有操作完成后,promise 就完全解决了。
<script> function add_positivenos_async(n1, n2) { let p = new Promise(function (resolve, reject) { if (n1 >= 0 && n2 >= 0) { //do some complex time consuming work resolve(n1 + n2) } else reject('NOT_Postive_Number_Passed') }) return p; } //Promise.all(iterable) Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]) .then(function(resolveValue){ console.log(resolveValue[0]) console.log(resolveValue[1]) console.log(resolveValue[2]) console.log('all add operations done') }) .catch(function(err){ console.log('Error',err) }) console.log('end') </script>
上述代码的输出如下 -
end 30 70 110 all add operations done
承诺.race()
该函数接受一系列 Promise 并返回第一个已解决的 Promise。
句法
下面提到了promise.race()函数的语法,其中iterable是一个可迭代对象。例如数组。
Promise.race(iterable)
例子
下面给出的示例采用异步操作的数组[add_positivenos_async(10,20),add_positivenos_async(30,40)]。
每当任何一个添加操作完成时,承诺就会得到解决。Promise 不会等待其他异步操作完成。
<script> function add_positivenos_async(n1, n2) { let p = new Promise(function (resolve, reject) { if (n1 >= 0 && n2 >= 0) { //do some complex time consuming work resolve(n1 + n2) } else reject('NOT_Postive_Number_Passed') }) return p; } //Promise.race(iterable) Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)]) .then(function(resolveValue){ console.log('one of them is done') console.log(resolveValue) }).catch(function(err){ console.log("Error",err) }) console.log('end') </script>
上述代码的输出如下 -
end one of them is done 30
Promise是在 JavaScript 中实现异步编程的一种简洁方式(ES6 新功能)。在 Promise 之前,回调用于实现异步编程。让我们首先了解什么是异步编程及其使用回调的实现。
了解回调
一个函数可以作为参数传递给另一个函数。这种机制称为回调。回调在事件中会有帮助。
下面的例子将帮助我们更好地理解这个概念。
<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()方法中,通知是通过发送短信和发送电子邮件来发生的。因此,notifyAll 方法的调用者必须传递两个函数作为参数。每个功能都承担一个职责,例如发送短信和发送电子邮件。
成功执行上述代码后将显示以下输出。
starting notification process Sms send .. Email send .. End of script
在上面提到的代码中,函数调用是同步的。这意味着 UI 线程将等待完成整个通知过程。同步调用变成阻塞调用。现在让我们了解非阻塞或异步调用。
了解异步回调
考虑上面的例子。
要启用该脚本,请执行对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
实现承诺的第一步是创建一个使用承诺的方法。假设在此示例中,getSum()方法是异步的,即它的操作不应阻止其他方法的执行。此操作完成后,它将稍后通知调用者。
以下示例(步骤 1)声明一个 Promise 对象“var Promise”。Promise 构造函数首先使用函数来成功完成工作,然后使用另一个函数以防发生错误。
Promise通过resolve回调返回计算结果,并传入结果,即n1+n2
步骤 1 - 解析(n1 + n2);
如果 getSum() 遇到错误或意外情况,它将调用 Promise 中的reject回调方法,并将错误信息传递给调用者。
步骤 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; }
第二步详细说明调用者的实现(STEP 2)。
调用者应使用“then”方法,该方法采用两种回调方法 - 第一个用于成功,第二个用于失败。每种方法都采用一个参数,如以下代码所示。
getSum(5, 6) .then(function (result) { console.log(result); }, function (error) { console.log(error); });
成功执行上述代码后将显示以下输出。
11
由于 getSum() 的返回类型是 Promise,因此我们实际上可以有多个“then”语句。第一个“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 提供了一种漂亮而干净的方式来处理回调。