1.引言
关于如何逐步运行异步函数这种问题已经在网上搜了很久了。有用,但不是很有用,至少能让我知道有Async/Await和Promise这两种东西。
众所周知JS为了提升运行效率会优先执行无需等待的代码,需要耗时很长时间的代码会自动创建至子线程运行,等运行完成后再通知主线程。这种情况等运行完成,那些需要取当前函数结果的代码早就被执行完了 。废话不多说,下面的例子展示的通常情况下的逐步运行的实现及我特殊要求下的优化代码。
2.例子
目前我需要发送XHR请求,待结果返回会传递给相关的数据处理函数,数据处理函数会将返回的JSON数据转换成CSV文件所需的文本格式,最后合并到一个全局变量中。待上述操作完成后,再调用CSV导出函数,完成数据导出。示例代码如下:
var csvData = ""
function doGet(url) { // 发送Get请求
return new Promise((resolve, reject) => {
let req = new XMLHttpRequest();
req.open('Get', url);
req.send();
req.onload = function() {
if (req.status == 200) {
resolve(req.response)
} else {
reject(Error("Network Error"))
}
}
req.onerror = function() {
reject(Error("Network Error"))
}
})
}
function parseData() {
// 处理数据..
//处理完合并到csvData中
}
function exportCSV() {
//CSV导出函数
}
async function main() {
const data1 = await doGet()
parseData(data1)
const data2 = await doGet()
parseData(data2)
exportCSV()
}
main()
但就是不知道哪里出的问题,解析数据的函数并没有等待请求函数的返回,就直接运行解析了。这样就会导致整个脚本运行错误。
那么我们是不是可以直接在解析函数的参数进行等待,给解析函数也加一个Promise,就像下面这样:
var csvData = ""
function doGet(url) { // 发送Get请求
return new Promise((resolve, reject) => {
let req = new XMLHttpRequest();
req.open('Get', url);
req.send();
req.onload = function() {
if (req.status == 200) {
resolve(req.response)
} else {
reject(Error("Network Error"))
}
}
req.onerror = function() {
reject(Error("Network Error"))
}
})
}
function parseData() {
return new Promise((resolve) => {
// 处理数据..
//处理完合并到csvData中
// ...
resolve() //完成后提交完成信号
})
}
async function main() {
await parseData(await doGet("http://localhost"))
await parseData(await doGet("http://localhost"))
exportCSV()
}
function exportCSV() {
//CSV导出函数
}
main()
就这么简单,await套await,好看又高效。虽然只是一个小小的变动,但实现真的花了我一天的时间。全在处理这个问题。特此记录下,给未来的我和有缘人一个提醒。
发表回复