首先看下ES6的Promise接口:
interface Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>, onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>;
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>): Promise<TResult>;
/**
* Creates a new Promise with the same internal state of this Promise.
* @returns A Promise.
*/
then(): Promise<T>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult>(onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch(onrejected: (reason: any) => T | PromiseLike<T>): Promise<T>;
}
发现无论是catch的参数还是then的第二个参数,都叫onrejected
下面是我的测试代码:
function c() {
return new Promise((resolve, reject) => {
console.info('begin do something');
setTimeout(() => {
// resolve("result");
reject("reject");
}, 2000);
// throw new Error("悲剧了");
});
}
// c().catch((err) => { console.info(err); });
c().then((ret) => {
console.info(ret);
}).catch((err) => {
console.info(err);
});
- 只要有
throw new Error("悲剧了");
就会走then的第二个参数或者catch,这取决于有then有没有第二个参数,有的话就走then的第二个参数,没有的话就走catch,
then的第二参数的优先级比catch高,
function c() {
return new Promise((resolve, reject) => {
console.info('begin do something');
// setTimeout(() => { // resolve("result"); reject("reject"); }, 2000);
reject("reject");
throw new Error("悲剧了");
});
}
这样的话输出就是 reject
Promise中resolve和reject不能同时执行,二选一,
then的优先级比catch高,所以一般在then中写第二个参数,不写catch就可以了。
我用的是vscode 写的 ts文件 配置task.json去编译ts到js 然后调试就方便了
vue中如何让第一个事件执行完之后再执行下一个事件?
一个小伙伴的提问:
fn1(){
fn2();
fn3();
}
怎样做才能使fn2执行完之后再执行fn3?
回答
同步的话可以这么写,异步这么写好像行不通
!function () {
var fn2 = function () {
return Promise.resolve("fn2")
}
var fn3 = function () {
return Promise.resolve("fn3")
}
void function fn1() {
fn2().then(function (val) {
console.info(val);
return fn3();
}).then(function (val) {
console.info(val);
});
}()
}()
异步写法:
!function () {
var fn2 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("fn2");
}, 1000);
});
}
var fn3 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("fn3");
}, 1000);
})
}
void function fn1() {
fn2().then(function (val) {
console.info(val);
return fn3();
}).then(function (val) {
console.info(val);
});
}()
}()
axios 异步请求的封装:
项目中用到封装一个请求函数,在后面每个vue组件中都可以调用,回调的话在一个组件中调用父组件的this.request()后,子组件拿不到请求完成或者失败的状态,所以这个时候需要promise来解决这个问题。
模拟ajax
function request(status) {
return new Promise(function (resolve, reject) {
if (status === 200 || status === 400) {
resolve({ errCode: status, data: 88 })
} else {
reject({ errCode: status, data: 88 });
}
}).then(function (res) {//请求后,后台返回的数据
// if (res.errCode === 200) {
// return Promise.resolve(res.data);
// } else {
// return Promise.reject(res.data);
// }
return new Promise(function (resolve, reject) {
if (res.errCode === 200) {
return resolve(res.data);
} else {
return reject(res.data);
}
});
}, function (err) {
return err;
});
}
request(400).then(function (data) {
console.info(data);
}, function (err) {
console.info(err);
});
第一个new promise是模拟ajax请求,后台返回有不同的status状态,一般200的话是请求成功,并且得到正确的数据,而其他的请求即使成功,走的是then的第一个函数,status是不同的状态码,有些状态码需要在公共的方法中处理,就是在这里处理,有些需要到每个组件的then里面处理,axios的错误状态捕获有,可以在then的第二个参数中捕获,或者在catch里面捕获,then第二个参数的优先级高于catch,所以处理一个就行了,上面代码是then里面处理异常,也可以在catch处理:
function invoke(res) {
return Promise.resolve(res)
.then(res => {
console.log(res += '!');
return res;
})
.then(res => {
console.log(res += '!');
return Promise.reject("end"); //此处返回了一个新的promise
})
.catch(res => {
console.log(res);
// return res; //此处也返回了一个新的resolved的promise
return Promise.reject(res);//此处返回一个新的rejected的promise
})
.then(res => {
console.log(res += '!'); //肯定会执行了
}, err => {
console.info(err += '!');
});
}
invoke('hello');
// hello!
// hello!!
// end
// end!
从接口也可以看出来,catch是可以再次返回promise的。
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch(onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult>(onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
实际项目中:
return axios(config).then(response => {
var res = response.data;
var promise = new Promise((resolve, reject) => {
if (res.status !== 1) {
reject(res);
} else {
resolve(res);
}
})
return promise;
}, err => {
return Promise.reject(err);//1.超时的话,
}).catch((exp) => {
console.info("exception:", exp);//2.
return Promise.reject(exp);
});
login.vue
this.$http('student/login', "post", form).then((res) => {
localStorage.setItem("token", res.token);
this.$router.push("/index");
}, (err) => {
console.info("login err");//并不会走这里
}).catch(exp => {
console.info(exp);//3.
});
删除一些配置:
return axios(config).then(response => {
var res = response.data;
var promise = new Promise((resolve, reject) => {
if (res.status !== 1) {
reject(res);
} else {
resolve(res);
}
})
return promise;
}, err => {
return Promise.reject(err);//1.超时
});
login.vue
this.$http('student/login', "post", form).then((res) => {
localStorage.setItem("token", res.token);
this.$router.push("/index");
}, (err) => {
console.info("login err");//并不会走这里,可能和axios这个库有关系
});
最后改进为两边都使用catch捕获:
return axios(config).then(response => {
var res = response.data;
var promise = new Promise((resolve, reject) => {
if (res.status !== 1) {
reject(res);
} else {
resolve(res);
}
})
return promise;
}).catch((exp) => {
console.info("exception:", exp);
return Promise.reject(exp);
});
login.vue
this.$http('student/login', "post", form).then((res) => {
localStorage.setItem("token", res.token);
this.$router.push("/index");
}).catch(exp => {
console.info(exp);
});
网友评论