在jquery时代,如果一个有几个请求a,b,c,然后每个请求都需要用到上一个请求返回的数据的话,我们就会写这样的代码
$.ajax({url:a, data:null, success: (adata) => {
$.ajax({url:b, data: adata, success: (bdata) => {
$.ajax({url:c, data:bdata, success: (cdata) => {
console.log(cdata)
}})
}})
}})
可以看到,我们陷入到多层的回调中,而且也不美观。这个时候就产产生了几个解决异步问题的方法。
Promise
Promise本身是一个构造函数,里面的参数是一个函数,new Promise( (resolve, reject) => {} )
,可以看到函数里有两个参数,Promise一共有三个状态,pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。状态改变就会进入到promise 的then方法里进行下一步操作。
多层回调时,可以这样写
const log = console.log.bind(console);
new Promise((resolve, reject) => {
axios({
method: "post",
url: "http://api.nohttp.net/upload",
data: JSON.stringify({ age: 11 }),
headers: { 'Content-Type': 'application/json', }
}).then((res) => resolve(res.data))//通过resolve传过去的数据,
可以在后面的then方法里接收到。
}).then((adata) => new Promise((resolve, reject) => {
axios({
method: "post",
url: "http://api.nohttp.net/upload",
data: JSON.stringify(adata),
headers: { 'Content-Type': 'application/json', }
}).then((res) => resolve(res.data))
})).then((res) => log(res)).catch((err) => log(err))
catch会在捕捉到错误的时候执行,如果让他执行呢,在Promise里执行,
reject(err)
,和resolve同理,catch方法会接收到reject传过来的参数
如果是有个两个请求a,b,b请求的时候并不需要a返回的数据,但你想要在a,b两个请求都返回之后再去做某些操作的话,可以用Promise.all()
let a = new Promise(...);
let b = new Promise(...);
Promise.all( [a, b] ,(data) => {
console.log(data)//data拿到的是两个Promise返回的数据,以数组的形式返回
})
Generator
const log = console.log.bind(console);
let request = (param) => new Promise((resolve, reject) => {
axios({
method: "post",
url: "http://api.nohttp.net/upload",
data: JSON.stringify(param),
headers: { 'Content-Type': 'application/json', }
}).then((res) => {
resolve(res.data)
})
});
function* foo() {
const data = yield request({ age: 11 });
const finallyData = yield request({ ...data })
log(finallyData)
return
}
function run(gen) {
var g = gen();
function go(data) {
var result = g.next(data);
if (result && result.done) return;
result.value.then(function (data) {
go(data);
});
}
go();
}
run(foo);