blog
blog copied to clipboard
【面经】字节跳动 三面8:顺序发送 4 个请求 a,b,c,d,要求按照顺序输出
顺序发送 4 个请求 a,b,c,d,要求按照顺序输出
利用数组缓存,再按照标志依次输出
function getData(urls) {
// 感谢 @jinxin0112 的指正
return new Promise((resolve, reject) => {
const res = [], len = urls.length;
urls.forEach((url, i) => {
fetch('http://localhost:8080' + url).then(data => data.json())
.then(data => {
res[i] = { data, printed: false }; // 将数据放入缓存数组
let flag = true;
for (let j = 0; j < len && flag; j += 1) {
if (res[j]) { // 如果标志为 j 的有返回值,则继续
if (!res[j].printed) {
console.log(res[j].data);
res[j].printed = true;
j === len - 1 && resolve(res.map(o => o.data))
}
} else { // 无返回值,则跳出
flag = false;
}
}
}, reject);
});
})
}
const listPromise = getData(['/data.json', '/data2.json', '/data3.json', '/data4.json']);
listPromise.then(res => console.log(res));
// server.js 测试:模拟各个请求延迟返回
const express = require('express');
const cors = require('cors');
const app = express();
const getTime = () => Math.floor(Math.random() * 4 * 1000);
app.use(cors({ origin: '*' }));
app.use('/data.json', (req, res) => {
setTimeout(() => res.end(JSON.stringify({ a: 1 })), getTime());
});
app.use('/data2.json', (req, res) => {
setTimeout(() => res.end(JSON.stringify({ b: 2 })), getTime());
});
app.use('/data3.json', (req, res) => {
setTimeout(() => res.end(JSON.stringify({ c: 3 })), getTime());
});
app.use('/data4.json', (req, res) => {
setTimeout(() => res.end(JSON.stringify({ d: 4 })), getTime());
});
app.listen(8080, () => console.log('the app is running at http://localhost:8080'));
这题不能用 promise 吗
这题不能用 promise 吗
不清楚,欢迎指教哦
Promise.all 包4个fetch ?
Promise.all 包4个fetch ?
读题哦,是顺序发送,promise.all 是并发。然后是一个请求如果拿到结果,并且顺序为1,就马上输出,如果顺序为2,等顺序为1的请求输出后再输出,promise.all 是等全部请求都成功了才返回结果
function getData(urls) {
return new Promise((resolve, reject) => {
const res = Array.from({ length: urls.length });
urls.forEach((url, i) =>
fetch(url).then(data => {
res[i] = [i, data];
check();
}, reject)
);
function check(i) {
const realRes = res.filter(Boolean);
for (let k = 0; k < realRes.length; k++) {
if (realRes.map(([j]) => j)[k] !== k) return;
}
resolve(realRes.map(([_, data]) => data));
}
});
}
@lawler61 你这个直接return res怕是不得行哦
function getData(urls) { return new Promise((resolve, reject) => { const res = Array.from({ length: urls.length }); urls.forEach((url, i) => fetch(url).then(data => { res[i] = [i, data]; check(); }, reject) ); function check(i) { const realRes = res.filter(Boolean); for (let k = 0; k < realRes.length; k++) { if (realRes.map(([j]) => j)[k] !== k) return; } resolve(realRes.map(([_, data]) => data)); } }); }
你这个 realRes 没把数组锁住,先返回的数据会白 resolve 掉,再者 check 算法遍历数组太多次,数据多了会造成性能问题哦
@lawler61 你这个直接return res怕是不得行哦
你说的这个是对的哈,整体包个 promise 即可
受教了。。😄
async await不行吗
async await不行吗
可以给个demo,不过请理解题目,是顺序(并行)发送,不是一个请求发送且响应后再发下一个,那这就不是面试题了
试了一下用Promise.all好像确实可以
let url = 'http://localhost:8080'
async function p1(param) {
return await fetch(url + param).then(res => res.json()).then(res => res)
}
async function p2(param) {
return await fetch(url + param).then(res => res.json()).then(res => res)
}
async function p3(param) {
return await fetch(url + param).then(res => res.json()).then(res => res)
}
async function p4(param) {
return await fetch(url + param).then(res => res.json()).then(res => res)
}
Promise.all([p1('/data.json'), p2('/data2.json'), p3('/data3.json'), p3('/data4.json')]).then(res => {
console.log(res, '结果') //[1,2,3,4]
})
const express = require('express'); const cors = require('cors'); const app = express();
const getTime = () => Math.floor(Math.random() * 4 * 1000);
app.use(cors({ origin: '*' }));
app.use('/data.json', (req, res) => { setTimeout(() => res.end(JSON.stringify({ a: 1 })), 5000); });
app.use('/data2.json', (req, res) => { setTimeout(() => res.end(JSON.stringify({ b: 2 })), 1000); });
app.use('/data3.json', (req, res) => { setTimeout(() => res.end(JSON.stringify({ c: 3 })), 600); });
app.use('/data4.json', (req, res) => { setTimeout(() => res.end(JSON.stringify({ d: 4 })), 100); });
app.listen(8080, () => console.log('the app is running at http://localhost:8080'));
@gaoxinxiao 是a一回来就输入哦,如果是 b 先回来,要等a输出了,才接着输出,而不是Promise.all 所有接口完成后才看到接口。即使是Promise.all 原理能不能手写出来呢~
@gaoxinxiao是一回来就输入哦,如果是b先回来,要等一个输出,才输出,而不是承诺。所有接口所有完成后看到接口。即使是承诺。所有原理能不能手写出来呢~
我试了一下你写的那个例子也是一起回来的 就算先请求a然后a慢返回b先返回 也是一起展示的