js中异步处理-------callback,promise, async/await

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

你可能感兴趣的:(web前端,异步,promise,async/await,es6)