- ES6 教程
- ES6 - 首页
- ES6 - 概述
- ES6 - 环境
- ES6 - 语法
- ES6 - 变量
- ES6 - 运算符
- ES6 - 决策
- ES6 - 循环
- ES6 - 函数
- ES6 - 事件
- ES6 - Cookies
- ES6 - 页面重定向
- ES6 - 对话框
- ES6 - Void 关键字
- ES6 - 页面打印
- ES6 - 对象
- ES6 - 数字
- ES6 - 布尔值
- ES6 - 字符串
- ES6 - Symbol
- ES6 - 新的字符串方法
- ES6 - 数组
- ES6 - 日期
- ES6 - 数学
- ES6 - 正则表达式
- ES6 - HTML DOM
- ES6 - 迭代器
- ES6 - 集合
- ES6 - 类
- ES6 - Map 和 Set
- ES6 - Promise
- ES6 - 模块
- ES6 - 错误处理
- ES6 - 对象扩展
- ES6 - Reflect API
- ES6 - Proxy API
- ES6 - 验证
- ES6 - 动画
- ES6 - 多媒体
- ES6 - 调试
- ES6 - 图片地图
- ES6 - 浏览器
- ES7 - 新特性
- ES8 - 新特性
- ES9 - 新特性
- ES6 有用资源
- ES6 - 快速指南
- ES6 - 有用资源
- ES6 - 讨论
ES6 - Promise
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(),该函数异步地添加两个数字。如果传递正值,则 Promise 被 resolved。如果传递负值,则 Promise 被 rejected。
<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 链式调用
当我们需要依次执行一系列异步任务时,可以使用Promise 链式调用。当一个 Promise 依赖于另一个 Promise 的结果时,就会进行链式调用。这在下面的示例中显示
示例
在下面的示例中,add_positivenos_async() 函数异步地添加两个数字,如果传递负值则被拒绝。当前异步函数调用的结果作为参数传递给后续的函数调用。注意每个then()方法都有一个返回值。
<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 对象的一些常用方法:
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 将被完全 resolved。
<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
promise.race()
此函数接受一个 Promise 数组,并返回第一个已完成的 Promise。
语法
promise.race() 函数的语法如下所示,其中,iterable 是一个可迭代对象。例如数组。
Promise.race(iterable)
示例
下面给出的示例接受一个异步操作数组 [add_positivenos_async(10,20),add_positivenos_async(30,40)]。
只要任何一个加法操作完成,Promise 就会被 resolved。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
实现 Promise 的第一步是创建一个将使用 Promise 的方法。假设在这个例子中,getSum()方法是异步的,即它的操作不应该阻塞其他方法的执行。一旦此操作完成,它稍后将通知调用者。
以下示例(步骤 1)声明了一个 Promise 对象“var promise”。Promise 构造函数将两个函数作为参数,第一个用于工作成功完成,另一个用于发生错误时。
Promise 通过使用 resolve 回调并传入结果(即 n1+n2)来返回计算结果。
步骤 1 - resolve(n1 + n2);
如果 getSum() 遇到错误或意外情况,它将在 Promise 中调用 reject 回调方法并将错误信息传递给调用者。
步骤 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' 将有一个返回值。
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 提供了一种很好且简洁的方式来处理回调函数。