一般回调
- 一般回调会得到两个结果,成功或者失败
- 此时回调需要接受这两个参数,所以要搞两个回调来接受
对象中两个回调缩写的方法

这个方法的不足
-
名称不规范,可能是success可能是done
-
容易出现回调地狱,也就是会使得代码变得更加难以理解、追踪、调试和维护
回调地狱
-
难以进行错误处理
promise
可以实现关注点分离
let evt=a()
b(evt)
c(evt)
(1)b,c不需要牵扯到a的调用细节。
(2)a不需要知道或关注b,c是否存在。
回调则相反:
function a(b,c){
// do something
if(evt?) b(evt);
else c(evt)
}
(1)b,c需要牵扯到a的调用细节。
(2)a需要知道或关注b,c是否存在。
promise信任问题
promise调用then时,提供给then的回调只会被异步调用,(不同于回调,可能被同步也可能被异步调用),这些被调度的回调会在下一个异步时间点上依次被立即调用(插在异步队列的最前面)。
并且,这些then异步调用的任务队列会插在当前事件循环tick之后,而不是添加到事件循环队列的末尾(插在当前事件的末尾,下一个事件之前)。
promise会自动防止Zalgo的出现,因为只能被异步调用,不同于回调可能被同步也可能被异步调用,因此不用担心竞态条件。
(既可能在现在(同步)也可能在将来(异步)调用回调,由这种同步或异步行为引起的不确定性,被称为Zalgo)
promise用法
创建新的promise
一定要记住,使用return new Promise((resolve, reject)=> {})
就可以构造一个 Promise 对象
下面是完整的eg
ajax=(method,url,option)=>{
return new Promise((resolve,reject)=>{
const {success,fail}=options
//析构语法
//相当于options.success=success
//options.fail=fail的缩写
//下面是AJAX的四步构成
const request=new XMLHttpRequest()
request.open(method,url)
request.onreadystatechange=()=>{
if (request.readyState===4){
if(request.status<400){
resolve.call(undefined,request.response)
}
else if(request.status>=400){
reject.call(undefined,request)
}
}
}
request.send()
})
}
eg里面比较吊的语法解析
构析语法
const {success,fail}=options
//相当于options.success=success
//options.fail=fail两句的缩写
调用的时候
//普通回调
aiax(`get`,`/xxx`,{
success(response){},fail:(request,status)=>{}
})
//有两个回调,还是用了success和fail
//promise写法
aiax(`get`,`/xxx`.then((response)=>{},(request)=>{}))
//虽然也是回调,但不需要记住success和fail,then的第一个参数就一定是success
//第二个一定是fail
//这时候ajax返回了一个含有.then()方法的对象
总结
第一步
- 是使用
return new Promise((resolve, reject)=> {})
构造一个 Promise 对象 - 任务成功的时候调用resolve(result),失败则是reject(error)
- resolve和reject会自己再去调用成功和失败的函数
第二步 - 使用.then(success,fail)传入成功和失败的函数
缺点
- 无法使用请求头
- POST无法上传数据
这些都可以通过axios解决
比较高级的用法
- json可以自动响应,发现其content-type是json会自动调用JSON.parse
- 请求拦截器,这是加在请求里面的东西
- 响应拦截器,加在响应里面的东西
- 生成不同实例和对象,仅仅用于复杂场景
Tips: - Promise 不是前端发明的
- Promise 是目前前端解决异步问题的统一方案
- window.Promise 是一个全局函数,可以用来构造 Promise 对象
- 构造出来的 Promise 对象含有一个 .then() 函数属性
创建新的promise
resolve 和 reject 可以改成任何其他名字,不影响使用,但一般就叫这两个名字
任务成功的时候调用 resolve,失败的时候调用 reject
resolve 和 reject 都只接受一个参数
resolve 和 reject 并不是 .then(succes, fail) 里面的 success 和 fail,resolve 会去调用 success,reject 会去调用 fail
几个重要的api
Promise.prototype.then()
then()
方法返回一个 Promise
。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
let promise1 = new Promise(function(resolve, reject) {
resolve('Success!');
});
promise1.then(function(value) {
console.log(value);
// expected output: "Success!"
});
Promise.all()
Promise.all(iterable)
方法返回一个 Promise
实例,此实例在 iterable
参数内所有的 promise
都“完成(resolved)”或参数中不包含 promise
时回调完成(resolve);如果参数中 promise
有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise
的结果。
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
Promise.race
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
// Both resolve, but promise2 is faster
});
// expected output: "two"
网友评论