返回值只要是 Promise, 就可用 async/await 处理异步
服务端代码见文末
业务用例
登录
1.认证 获取 token
2.用 token 获取角色 id
3.用 token 和角色 id 获取菜单
类似 fetch 的异步请求 如 axios window.fetch umi-request dva/fetch 等
- 基本使用形式
new Promise(请求1)
.then(请求2(请求结果1))
.then(请求3(请求结果2))
.then(请求4(请求结果3))
.then(请求5(请求结果4))
.catch(处理异常(异常信息))
- 改写
直接在浏览器 console 可运行以下代码
async function login() {
const baseUrl = 'http://127.0.0.1:3005';
const { token } = await fetch(`${baseUrl}/auth`, {
method: 'POST',
data: { username: 'test', password: 'xxxxxxx' },
}).then(v => v.json()); // 这里后面在then一次是因为fetch直接返回的不是Promise 而是Response 而response.json()才会返回Promise
console.log('1.token->', token);
const roles = await fetch(`${baseUrl}/roles?token=${token}`).then(v => v.json());
console.log('2.roles->', roles);
const menus = await fetch(`${baseUrl}/menus?token=${token}&roles=${roles}`).then(v => v.json());
console.log('3.menus->', menus);
}
callback 方式返回处理, 以小程序为例,其他回调同理
- 基本使用形式
wx.request({
url: '请求一',
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json'
},
success (res) {
wx.request({
url: '请求二',
data: res.data,
header: {
'content-type': 'application/json'
},
success (res) {
......
}
})
}
})
- 改写
1.用 Promise 封装一个请求函数
const request = (url, options = { headers: {} }) => {
const baseUrl = 'http://127.0.0.1:3005';
const headers = {
'content-type': 'application/json',
...options.headers,
};
const method = options.method || 'GET';
const data = options.data || '';
return new Promise((resolve, reject) => {
wx.request({
url: baseUrl + url,
data,
method,
header: headers,
success(res) {
resolve(res);
},
fali(err) {
reject(err);
},
});
});
};
2.业务代码
const login = async () => {
const {
data: { token },
} = await request('/auth', { method: 'POST', data: { username: 'test', password: 'xxxxxxx' } });
console.log('1.token->', token);
const { data: roles } = await request('/roles', { data: { token } });
console.log('2.roles->', roles);
const { data: menus } = await request('/menus', { data: { token, roles } });
console.log('3.menus->', menus);
};
定时器
- 改写
const sleep = time => {
return new Promise(resolve => {
console.log(`等待${time}秒...`);
setTimeout(() => {
resolve(true);
}, time * 1000);
});
};
- 使用
const request = require('axios');
request.defaults.baseURL = 'http://127.0.0.1:3005';
async function login() {
const {
data: { token },
} = await request('/auth', { method: 'POST', data: { username: 'test', password: 'xxxxxxx' } });
console.log('1.token->', token);
await sleep(2);
const { data: roles } = await request('/roles', { params: { token } });
console.log('2.roles->', roles);
await sleep(2);
const { data: menus } = await request('/menus', { params: { roles, token } });
console.log('3.menus->', menus);
}
任务间隔定时器
传统 setInterval 是每个一段固定的时间调用一次任务,不关心任务时长,期望一个关心任务时长的 interval
- 以任务为间隔的定时器,关心任务时长,即等到所有任务执行完成后,再间隔一定时间,开始下一次任务
const interval = async (task, time, id) => {
while (true) {
if (!global[id]) break;
await new Promise(res => {
res(task());
});
await sleep(time);
}
};
const addInterval = (task, time = 5) => {
const id = Symbol();
global[id] = true;
setTimeout(() => {
interval(task, time, id);
}, 0);
return id;
};
const delInterval = id => {
global[id] = false;
};
- 使用
以上面的login
为例
const id = addInterval(login, 2); //任务间隔2s
setTiemt(() => {
// 在某个时间段或者某个操作时停止循环
delInterval(id);
}, xxx);
服务端代码示例
const app = require('express')();
const bodyParser = require('body-parser');
const { sleep } = require('./tools');
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
}),
);
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
res.header('X-Powered-By', ' 3.2.1');
res.header('Content-Type', 'application/json;charset=utf-8');
next();
});
app.post('/auth', (req, res) => {
const { username } = req.body;
console.log(username);
res.send({
id: 1,
name: username,
age: 18,
token: `absfgsakjdhjskahdsklh`,
});
});
app.post('/auth/slow', async (req, res) => {
const { username } = req.body;
console.log(username);
await sleep(4);
res.send({
id: 1,
name: username,
age: 18,
token: `absfgsakjdhjskahdsklh`,
});
});
app.get('/roles', (req, res) => {
res.send([1, 2, 3]);
});
app.get('/roles/slow', async (req, res) => {
await sleep(4);
res.send([1, 2, 3]);
});
app.get('/menus', (req, res) => {
res.send([
{ name: '首页', path: '/' },
{ name: '用户管理', path: '/users' },
]);
});
app.get('/slow', async (req, res) => {
const second = Math.round(Math.random() * 7) + 1;
await sleep(second);
// res.append('Access-Control-Allow-Origin','*')
res.send({
code: 0,
data: Date.now(),
msg: 'ok',
});
});
app.listen(3005, () => {
console.log(`server run time: ${Date.now()}`);
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。