await is a reserved word报错
该报错提示,await 是保留字 ,一开始由于使用的框架是 react ,某个接口需要在 state 更新后,再进行调用,情况类似如下代码(为了演示故意写成如下情况)。
import { Restful } from './Restful'
...
/**
* @private
* @method 查询使用接口数据
* @param {object} data
* @returns undefined
* @author
*/
onDataChange = (data) => {
this.setState({
data
}, () => { // 该方法需要先把数据更新到state中,然后再从state中获取数据进行查询
let dataID = null;
//查询接口数据
let queryData = {
method: 'POST',
url: '/restful/query/data',
data: {
code: this.state.data.code,
data: this.state.data.param
}
};
Restful.fetch(queryData).then((response) => { //先查询这个接口,获取ID
if (response.data.code === 0) {
dataID = response.data.dataID;
}
});
//使用接口数据
let useData = {
method: 'POST',
url: '/restful/use/data',
data: {
id: dataID
}
};
Restful.fetch(useData).then((response) => { //用上面查询到的ID,再调用这个接口
if (response.data.code === 0) {
...
}
});
});
}
上面的 restful 是封装的 axios 接口,类似下方代码。
export default class Restful {
/**
* 外部调用发送请求
* @param {object} fetchObj 请求时传入参数
*/
static fetch(fetchObj) {
return new Promise(function (resolve, reject) {
axios({
...fetchObj,
timeout: 30000,
headers: {
Authorization: window['token'],
'Content-Type': 'application/json'
}
}).then(function (response) {
resolve(response);
}).catch(function (response) {
reject(response);
});
});
}
}
上面方法中,我想先执行 queryData ,查询到 id 后,在拿着 id 去调用下一个接口,一开始直接在最外层的方法上增加了 async 如下所示。
onDataChange = (data) => {
async function changeData(data) {
this.setState({
data
}, () => { // ** 此处是需要修改的点
let dataID = null;
//查询接口数据
let queryData = {
...
}
};
await Restful.fetch(queryData).then((response) => { //这里直接报错await is a reserved word
if (response.data.code === 0) {
dataID = response.data.dataID;
}
});
//使用接口数据
let useData = {
...
};
await Restful.fetch(useData).then((response) => {
if (response.data.code === 0) {
...
}
});
});
}
changeData(data);
}
上面代码运行直接报错 await is a reserved word 原因在上面 ** 符号处,原因是 await 只能在 async 函数 中使用(这句话很重要)。
上面存在函数嵌套,虽然外层函数设置成了 async 函数 但是其内部存在一个回调函数,严格意义上来说,这个回调函数,不属于 async function changeData 的内部,所以该回调函数没有设置成 async,那么其内部的 await就不会生效,而是当做变量去处理,同时这个又是关键字,才报出来那个错。
修改方法很简单,把外面的那个 async 放到回调函数前面就可以了,效果如下
onDataChange = (data) => {
// 原来在这里的 async 删掉
this.setState({
data
}, async function() { // 把这个回调函数设置成 async函数
let dataID = null;
//查询接口数据
let queryData = {
...
};
await restful.fetch(queryData).then((response) => {
if (response.data.code === 0) {
dataID = response.data.dataID;
}
});
//使用接口数据
let useData = {
...
};
await restful.fetch(useData).then((response) => {
if (response.data.code === 0) {
...
}
});
});
}
需要注意的是,如果 async 函数 内部没有 await 那么它和普通函数一样。
举一反三
上面代码中,我故意加入了 restful 封装接口的使用,是应为它也符合回调函数设置成 async 的情况。举个例子,我想先查询第一个接口,然后第二个,然后第三个。
async function query() { // 如果 async 写在这里,await那里还是会报错
Restful.fetch(first).then((response) => {
await Restful.fetch(second).then((response) => {
});
await Restful.fetch(third).then((response) => {
});
})
}
正确写法
Restful.fetch(first).then(async function(response) { //写在这里才可以正常运行
await Restful.fetch(second).then((response) => {
});
await Restful.fetch(third).then((response) => {
});
})
yield is a reserved word报错
yield is a reserved word 报错原因和上面 await 一样,yield 必须写在 generator 函数 内部,回调函数不属于某个函数,而是属于在满足某些条件后,执行的函数。写法如下
Restful.fetch(first).then((response) => {
Restful.fetch(second).then((response) => {
let useData = generator(); //在第二个异步调用中使用 generator 函数
useData.next();
useData.next();
});
fucntion* generator() { //把第三个要执行的异步设置成 generator 函数
yield Restful.fetch(third).then((response) => {
});
}
})
个人感觉,generator 函数 的作用在于,可以手动的操作函数运行,让谁执行,让谁停止,变成了完全可控状态,不过相比于async 使用起来还是相对麻烦一点。