Promise应用
创建一个 Promise 对象
let promise = showLabelText() {return new Promise((resolve, reject) => {axios({method: "post",url: "/code/expose/interface/queryActionPlan",data: { situationOneId: '19999', labels: ['1', '2', '3'] }}).then(response => {this.labelTextData = response.data;resolve(response.data); // 请求成功后解析Promise}).catch(error => {reject(error); // 请求失败后拒绝Promise})});
}// 处理 Promise 的成功情况
promise.then(result => {console.log("成功:", result);
}).catch(error => {console.log("失败:", error);
}).finally(() => {console.log('无论成功或失败,finally 语句块都会执行');
})
在上述示例中,我们创建了一个Promise对象,并在其回调函数中进行异步操作。根据条件判断,决定是调用resolve方法还是reject方法。
如果异步操作成功,我们调用resolve方法并传递成功的结果。然后,可以使用.then方法来处理Promise的成功情况,接收并处理成功的结果。
如果异步操作失败,我们调用reject方法并传递失败的原因。然后,可以使用.catch方法来处理Promise的失败情况,接收并处理失败的原因。
通过这种方式,我们可以使用Promise对象来处理异步操作的结果,并以链式的方式进行成功和失败的处理。
Promise 常用方法:
.then()方法:用于注册成功的处理程序。可以链式调用多个.then()方法来处理Promise的成功结果。
.catch()方法:用于注册失败的处理程序。通常在链式调用的最后使用,以捕获和处理Promise的失败情况。
// 假设我们有一个函数,用于从服务器获取用户信息
function fetchUserInfo(orgCode) {return new Promise((resolve, reject) => {// 假设这是异步获取用户信息的操作axios({method: "post",url: "/getUserInfo",data: { orgCode: orgCode }}).then(response => {resolve(response.data); // 请求成功后解析Promise})});
}// 假设我们有另一个函数,用于从服务器获取用户订单
function fetchUserOrders(userInfo) {return new Promise((resolve, reject) => {// 假设这是异步获取用户订单的操作axios({method: "post",url: "/getUserOrders",data: { userInfo: userInfo }}).then(response => {resolve(response.data); // 请求成功后解析Promise})});
}// 假设我们有最后一个函数,用于发送邮件给用户
function sendEmailToUser(userInfo, orders) {return new Promise((resolve, reject) => {// 假设这是异步发送邮件的操作axios({method: "post",url: "/sendEmail",data: { userInfo: userInfo,orders:orders }}).then(response => {resolve(response.data); // 请求成功后解析Promise})});
}// 使用 Promise 链式调用来处理异步操作
fetchUserInfo(123) // 获取用户信息.then(userInfo => {console.log('用户信息:', userInfo);return fetchUserOrders(userInfo); // 获取用户订单}).then(orders => {console.log('用户订单:', orders);return sendEmailToUser(userInfo, orders); // 发送邮件给用户}).then(result => {console.log('最终结果:', result);}).catch(error => {console.error('发生错误:', error);});
.all()方法:用于处理多个Promise对象的并发执行,并等待所有Promise都完成。
.race()方法:用于处理多个Promise对象的竞争执行,只等待第一个完成的Promise。
let promises = [new Promise((resolve, reject) => {// 异步操作 1setTimeout(() => {resolve("结果 1");}, 1000);}),new Promise((resolve, reject) => {// 异步操作 2setTimeout(() => {resolve("结果 2");}, 2000);}),new Promise((resolve, reject) => {// 异步操作 3setTimeout(() => {resolve("结果 3");}, 3000);})
];try {// 使用 Promise.all 等待所有异步操作完成const results = Promise.all(promises).then(results => {console.log("所有异步操作完成:", results);// 输出: [ '结果 1', '结果 2', '结果 3' ]})
} catch (error) {console.error("Error fetching data:", error);
}
Promise.race([promise1, promise2]).then(result => {console.log("第一个完成的 Promise 的结果:", result);// 输出: 结果 1 或 结果 2,具体取决于哪个 Promise 先完成
});
async/await
async/await 是以更舒适的方式使用 promise 的一种特殊语法,同时它也非常易于理解和使用。
让我们以 async 这个关键字开始。在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被包装在一个 resolved 的 promise 中。
例如,下面这个函数返回一个结果为 1 的 resolved promis:
async function f() {return 1;
}f().then(alert); // 1
我们也可以显式地返回一个 promise,结果是一样的:
async function f() {return Promise.resolve(1);
}f().then(alert); // 1
所以说,async 确保了函数返回一个 promise,也会将非 promise 的值包装进去
还有另外一个叫 await 的关键词,它只在 async 函数内工作。
// 只在 async 函数内工作
let value = await promise;
关键字 await 让 JavaScript 引擎等待直到 promise 完成(settle)并返回结果。
这里的例子就是一个 1 秒后 resolve 的 promise:
async function f() {let promise = new Promise((resolve, reject) => {setTimeout(() => resolve("done!"), 1000)});let result = await promise; // 等待,直到 promise resolve (*)alert(result); // "done!"
}f();
这个函数在执行的时候,“暂停”在了 (*) 那一行,并在 promise settle 时,拿到 result 作为结果继续往下执行。所以上面这段代码在一秒后显示 “done!”。
让我们强调一下:await 实际上会暂停函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。这个行为不会耗费任何 CPU 资源,因为 JavaScript 引擎可以同时处理其他任务:执行其他脚本,处理事件等。
相比于 promise.then,它只是获取 promise 的结果的一个更优雅的语法。并且也更易于读写。
注意:
不能在普通函数中使用 await
如果我们尝试在非 async 函数中使用 await,则会报语法错误:
总结
函数前面的关键字 async 有两个作用:
让这个函数总是返回一个 promise。
允许在该函数内使用 await。
Promise 前的关键字 await 使 JavaScript 引擎等待该 promise settle,然后:
如果有 error,就会抛出异常 —— 就像那里调用了 throw error 一样。
否则,就返回结果。
这两个关键字一起提供了一个很好的用来编写异步代码的框架,这种代码易于阅读也易于编写。
有了 async/await 之后,我们就几乎不需要使用 promise.then/catch,但是不要忘了它们是基于 promise 的,因为有些时候(例如在最外层作用域)我们不得不使用这些方法。并且,当我们需要同时等待需要任务时,Promise.all 是很好用的。