Promise 对象
- Promise 对象是异步编程的一种解决方案。
- 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
该状态的特点:
- Promise 异步操作有三种状态:pending(进行中)、fulfilled /resolve(成功)和 rejected(失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。
- Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。
该状态的缺点:
- 无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
- 当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
示例代码:
let div = document.getElementById("imgParent");
function loadImg(src){
return new Promise(function(resolve,reject){
setTimeout(function(){
let img = new Image();//创建一个HTML的img元素
img.src = src;
div.appendChild(img);
img.width = 400;
img.height = 300;
//如果该元素的onload事件触发,说明元素正常加载了
img.onload = function(){
resolve(img);
}
img.onerror = function(){
reject("图片加载失败:"+src)//返回一个rejected状态的Promise对象
}
},2000);//设置延迟3秒加载图片,异步操作
})
}
let proml = loadImgreturn loadImg('./img/1.jpg'); ; //得到加载图片1的promise对象
proml.then(function(img){ //成功加载图片1,成功回调
console.log("图片1加载成功:"+img.src);
return loadImgreturn loadImg('./img/2.jpg'); ; //返回加载图片2的promise对象
},function(msg){
console.log(msg);
}).then(function(img){
console.log("图片2加载成功:"+img.src);
return loadImg('./img/3.jpg'); //返回加载图片3的promise对象
},function(msg){
console.log(msg);
}).then(function(img){
console.log("图片3加载成功:"+img.src);
},function(msg){
console.log(msg);
});
该示例中的 then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
特点:
- 在 JavaScript 事件队列的当前运行完成之前,回调函数永远不会被调用。
- 通过 .then 形式添加的回调函数,不论什么时候,都会被调用。
- 通过多次调用
- 可以添加多个回调函数,它们会按照插入顺序并且独立运行。
- then 方法将返回一个 resolved 或 rejected 状态的 Promise
- 对象用于链式调用,且 Promise 对象的值就是这个返回值。
async 函数
async的语法
async function name([param[, param[, ... param]]]) { statements } //name: 函数名称。param: 要传递给函数的参数的名称。statements: 函数体语句。
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
await的语法
[return_value] = await expression;
expression: 一个 Promise 对象或者任何要等待的值。
await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。
示例:
//封装一个异步操作,2秒后把传入的数字乘以2
function doubleAfter2Seconds(num){
return new Promise(function(resolve,reject){
setTimeout(() => {
resolve(2 * num);
},2000)
});
}
//封装一系列连续的异步操作吗,打包
async function calc(){
//局部代码,按顺序进行(同步)
//await会让异步的流程先停下来等待
let result = await doubleAfter2Seconds(2);
result = await doubleAfter2Seconds(result);
result = await doubleAfter2Seconds(result);
console.log("最终的计算的结果:"+result);
}
calc();//先调用
console.log("calc异步计算调用完成!");
//总体代码流程异步的
结果:
注意:
- async 函数中可能会有 await 表达式,async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。
- await 关键字仅在 async function 中有效。如果在 async function 函数体外使用 await ,你只会得到一个语法错误。
- 正常情况下,await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。
await针对所跟不同表达式的处理方式:
- Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
- 非 Promise 对象:直接返回对应的值。