1. 回调函数callback
回调就是在异步操作之后把得到的值传递给回调函数进行处理。
function queryCity(latitude, longitude, callback) {
wx.request({
url: "/restapi/soa2/10398/json/LBSLocateCity",
method: "POST",
data: {
Latitude: latitude,
Longitude: longitude,
Language: "CN"
},
success: function (res) {
if (callback) {
callback(res)
}
},
fail: function () {
if (callback) {
var cbData = {};
cbData.error = "Request_Failed";
callback(cbData);
}
}
});
}
这里,使用一个定位的例子,定位是个异步操作,定位成功后,把数据传递到callback函数,定位失败,构建error信息,把error信息传递给callback。
这种写法,有一个不好的地方,如果callback也是异步,那么callback内部还要定义callback, 如果有多个异步,可以想象。。。
2. promise
promise就是对callback函数写法的改进,promise对象是一个构造函数,当new Promise()通常会立马执行,所以一般把new promise()封装在一个函数内部返回,需要调用的时候调用函数即可。
function ayncreq(){
return new Promise((resolve, reject) => {
cwx.request({
url: "/restapi/soa2/10398/json/LBSLocateCity",
method: "POST",
data: {
Latitude: latitude,
Longitude: longitude,
Language: "CN"
},
success: function (res) {
resolve(res)
},
fail: function () {
var cbData = {};
cbData.error = "Request_Failed";
reject(cbData)
}
});
})
}
promise就是封装一个异步操作,并在结束后把值通过resolve或者reject传递出来,并且在then方法中接受这个值。所以调用的时候:
ayncreq().then((data) => {
console.log(data)
})
一个promise对象只会封装一个异步操作,如果有多个异步操作,可以每个都返回一个promise对象,假如还存在ayncreq1,ayncreq2,调用:
ayncreq().then((data) => {
console.log(data)
return ayncreq1()
}).then((data) => {
console.log(data)
return ayncreq2()
}).then((data) => {
console.log(data)
})
即在每一个then方法中再返回一个promise对象,实现链式调用。在多个then连续调用的时候,每个中间then的onfulled函数必须存在return,来作为下一个then的输入。
需要注意的是除了resolve还有reject:
ayncreq().then(
(data) => {
console.log(data)
},
(data) => {
console.log('error')
}
)
但是一般并不这么用,我们可以使用catch代替reject, 除了有catch的作用外,在执行resolve的回调时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。
ayncreq()
.then(function(data){
console.log('resolved');
console.log(data);
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
最后,promise还有一个常用的all()方法,上面的多个异步操作,我们可以使用all来进行处理:
Promise.all([ayncreq(), ayncreq1(), ayncreq2()]).then(
(result ) => {
console.log(result)
}
)
这三个函数会并行执行,并不是顺序执行。也就是all函数中的异步操作是并行执行的,当所有结果成功返回时候按照请求时候的顺序返回结果, 也就是ayncreq的结果在前,即使它的结果来的比ayncreq1晚。
all函数中的异步操作是不能相互依赖的,比如ayncreq1()的运行依赖ayncreq()运行的结果,这种方法是不行的。
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。
Promise.race([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 打开的是 'failed'
})
race中的异步操作同样是并行执行的,哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态,所以它只会返回执行最快的异步操作中resolve()的值。
可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作。
3.async-await
async-await是promise和generator的语法糖,async-await 是建立在 promise机制之上的,使用非常简单:
async function Demo() {
let result = await Math.random();
console.log(result);
}
Demo();
async function demo01() {
return 123;
如果函数前面有async,则意味着这个函数总是返回一个promise,如果代码中有return <非promise>语句,JavaScript会自动把返回的这个value值包装成promise的resolved值。await可以等很多东西,它主要用于等待promise对象的状态被resolved。
async/await 最方便用在多个异步相互依赖的应用中,比如三个异步p1,p2,p3; p2依赖p1, p3依赖p2, 使用回调要三层,使用promise要三个then,
使用,使用await则非常清晰,比如下边这个例子:
function sleep(second, param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(param);
}, second);
})
}
async function test() {
let result1 = await sleep(2000, 'req01');
let result2 = await sleep(1000, 'req02' + result1);
let result3 = await sleep(500, 'req03' + result2);
console.log(`
${result3}
${result2}
${result1}
`);
}
test();
需要注意的是在处理reject时候最好使用try/catch.
4. async、await语法实现原理??
5.补充一个setTimeout、Promise、Async/Await 的区别
其中settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行;
promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。
最后关于如果实现一个promise请参考:
主要就是then完成回调函数注册,异步操作完成之后可以调用回调,链式调用、状态控制等。
https://www.jianshu.com/p/f77d8c61c69a
参考:
http://www.cnblogs.com/lvdabao/p/es6-promise-1.html
https://www.jianshu.com/p/5583e655ddc2
https://www.jianshu.com/p/dbda3053da20
https://www.jianshu.com/p/7e60fc1be1b2
https://segmentfault.com/a/1190000013292562?utm_source=channel-newest
https://segmentfault.com/a/1190000011526612?utm_source=tag-newest