Promise异步学习
是什么?
promise 是一个对象,它可能会在未来的某个时间产生一个值。并且你可以声明
- 未来获取到值时应该怎么做
- 如果出现异常怎么做
- 不论结果如何都要干的事情
怎么来的?
回调是怎么回事儿?
const getData = function() { // go fetch data from some API... // clean it up a bit and return it as an object: return data } const myData = getData() // 需要注意由于请求数据是异步操作,所以并不会等待获取到数据了,才执行下面这句话。 // 最终结果即使 myData 是undefine const pieceOfData = myData['whatever']
正确使用
const myData = getData() // if this is refactored to return a Promise... // 通过Fetch会返回一个Promise对象,我们告诉它当正确读取到数据时,应该怎么做 myData.then(function(data){ // .then() tells it to wait until the promise is resolved const pieceOfData = data['whatever'] // and THEN run the function inside })
怎么用?
基础用法
var p = new Promise(function(resolve, reject) { // Do an async task async task and then... if(/* good condition */) { resolve('Success!'); } else { reject('Failure!'); } }); p.then(function(result) { /* do something with the result */ }).catch(function() { /* error :( */ }).finally(function() { /* executes regardless or success for failure */ });
将原先的XMLHttpRequest优化为使用Promise
function get(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response); } else { reject(xhr.statusText); } }; xhr.send(); }); } // 写法一 get('story.json').then(function(response) { console.log("Success!", response); }, function(error) { console.error("Failed!", error); }); // 写法二: 更直观一点 get('story.json').then((response) => { console.log("Success!", response); }).catch((error) => { console.error("Failed!", error); })
使用类方法
var userCache = {}; function getUserDetail(username) { // In both cases, cached or not, a promise will be returned if (userCache[username]) { // Return a promise without the "new" keyword return Promise.resolve(userCache[username]); } // Use the fetch API to get the information // fetch returns a promise return fetch('users/' + username + '.json') .then(function(result) { userCache[username] = result; return result; }) .catch(function() { throw new Error('Could not find user: ' + username); }); }
Promise.all
当执行多个异步操作,希望所有异步操作都执行完了,再触发回调
具体做法Promise.all([promise1, promise2]).then(function(results) { // Both promises resolved }) .catch(function(error) { // One or more promises was rejected });
当然如果有任意一个异步操作失败,都会直接触发rejection,并且catch到第一个rejection的Promisevar request1 = fetch('/users.json'); var request2 = fetch('/articles.json'); Promise.all([request1, request2]).then(function(results) { // Both promises done! })
var req1 = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { resolve('First!'); }, 4000); }); var req2 = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { reject('Second!'); }, 3000); }); Promise.all([req1, req2]).then(function(results) { console.log('Then: ', results); }).catch(function(err) { console.log('Catch: ', err); });
Promise.race
该操作也是执行多个Promise,不同的是只要有一个Promise成功或失败,都会立刻触发var req1 = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { resolve('First!'); }, 8000); }); var req2 = new Promise(function(resolve, reject) { // A mock async action using setTimeout setTimeout(function() { resolve('Second!'); }, 3000); }); Promise.race([req1, req2]).then(function(one) { console.log('Then: ', one); }).catch(function(one, two) { console.log('Catch: ', one); });
实践说明
通过一个小的需求,通过不断的优化,回调->promise->sync/await
需求说明:
我们希望红绿灯能循环执行,比如红灯执行三秒后,执行绿灯,绿灯执行两秒后执行黄灯,黄灯执行一秒后再执行红灯。
基础函数:
function red() {
console.log("red...");
}
function green() {
console.log("green...");
}
function yello() {
console.log("yello...");
}
使用回调
const task = (time, color, callback) => {
setTimeout(() => {
if (color == "red") {
red();
}
if (color == "green") {
green();
}
if (color == "yello") {
yello();
}
callback();
}, time);
};
const step = () => {
task(1000, "red", () => {
task(3000, "green", () => {
task(2000, "yello", step);
});
});
};
step();
可以看到有很多的嵌套
执行Promise
const task = (time, color) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (color == "red") {
red();
}
if (color == "green") {
green();
}
if (color == "yello") {
yello();
}
resolve();
}, time);
});
};
const step = () => {
task(1000, "red")
.then(() => task(3000, "green"))
.then(() => task(2000, "yello"))
.then(() => step());
};
step();
通过一个个then保证依次顺序执行,代码简单化
使用sync/await
const task = (time, color) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (color == "red") {
red();
}
if (color == "green") {
green();
}
if (color == "yello") {
yello();
}
resolve();
}, time);
});
};
const step = async () => {
await task(1000, "red");
await task(3000, "green");
await task(2000, "yello");
step();
};
step();
通过sync/await 将代码进一步简化,通过函数调用的方式进行声明
解决现实问题
一个需求中,当用户执行某个操作时,会对操作数据状况进行校验,通过确认框进行用户提醒,当有多个情况需要确认时,会先进行第一个提示框提醒,点击确认后,再弹出第二个提示框进行确认。
最初实现方式
// 先服务再到款-确认订单状态
function check_order_status() {
let that = this;
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.associate_order"),
onOk: () => setTimeout(() => that.check_payment_status(), 350),
});
}
// 先服务再到款-确认到款状态
function check_payment_status() {
let that = this;
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.payment"),
onOk: () => setTimeout(() => that.check_invoice_status(), 350),
});
}
// 先服务再到款-确认开票状态
function check_invoice_status() {
let that = this;
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.invoice"),
onOk: () => that.drawbackQuotation(),
});
}
this.check_order_status();
可以看到函数之间耦合在一起,维护起来很麻烦,每个判断信息应该是独立的,通过外部去控制先后顺序
代码优化
// 先服务再到款-确认订单状态
function check_order_status() {
let that = this;
return new Promise((resolve, reject) => {
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.associate_order"),
onOk: () => resolve(),
});
});
}
// 先服务再到款-确认到款状态
function check_payment_status() {
let that = this;
return new Promise((resolve, reject) => {
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.payment"),
onOk: () => resolve(),
});
}
}
// 先服务再到款-确认开票状态
function check_invoice_status() {
let that = this;
return new Promise((resolve, reject) => {
this.$Modal.confirm({
title: this.info("title", "title_bar.return_draft"),
content: this.info("content", "title_bar.return_draft.invoice"),
onOk: () => resolve(),
});
}
}
const checkProccess = async () => {
await check_order_status()
await check_payment_status()
await check_invoice_status()
}
可以看到代码一下优雅可维护了许多
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 玲辰书斋!