Promise 串行面试题
Opened this issue · 0 comments
nbhaohao commented
问题
我们有 A, B 两个按钮,A 会发送一个请求,向服务端拿取数据,B 也会发送一个请求,向服务器拿取数据。
我们先点击 A, 再点击 B. 正常的表现是这样的:(这时候 A 的请求要花 500 毫秒,B 的请求要花 800 毫秒)
因为我们先点击 A 按钮,再点击 B 按钮,所以我们期待最后显示的是 B 的结果。
但是假如我们的操作不变,如果 A 请求的时间要比 B 请求的时间要久,即我们先点击 A 按钮,再点击 B 按钮,然后 B 的请求先返回了,然后再返回 A 的请求,Bug 就出现了。
由于我们后点击的 B 按钮,所以我们希望看到 B 按钮所请求到的内容,但是 A 请求的比较慢,所以它把内容覆盖掉了。
目前我们的代码如下:
<body>
<span>返回结果: <span id="result"></span></span>
<div></div>
<button id="buttonA">A</button>
<button id="buttonB">B</button>
</body>
const ajaxA = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve("结果A");
}, 2000);
});
};
const ajaxB = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve("结果B");
}, 1000);
});
};
const changeResult = msg => {
document.querySelector("#result").innerHTML = msg;
};
const testA = async () => {
const result = await ajaxA();
changeResult(result);
};
const testB = async () => {
const result = await ajaxB();
changeResult(result);
};
buttonA.onclick = testA;
buttonB.onclick = testB;
解法
我们需要 2 个队列,第一个队列用来记录发送请求的顺序,第二个队列用来存储请求的结果,第二个队列一旦产生结果,他需要检查一下,是不是属于第一个队列中先发的请求的,如果是,那么就显示,如果不是,那么就把这个请求结果先存起来,因为暂时用不到。
const requestArray = [];
const responseArray = [];
const ajaxA = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve("结果A");
}, 2000);
});
};
const ajaxB = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve("结果B");
}, 1000);
});
};
const changeResult = msg => {
document.querySelector("#result").innerHTML = msg;
};
const handleResponse = () => {
if (requestArray.length === 0) {
return;
}
const eraliestRequest = requestArray[0];
const responseItemIndex = responseArray.findIndex(
item => item.tag === eraliestRequest.tag
);
if (responseItemIndex === -1) {
return;
}
eraliestRequest.callback(responseArray[responseItemIndex].result);
requestArray.shift();
responseArray.splice(responseItemIndex, 1);
handleResponse();
};
const testA = async () => {
const tag = `${Date.now()}-testA`;
requestArray.push({
tag,
callback: result => {
console.log("执行 tagA 的回调");
changeResult(result);
}
});
const result = await ajaxA();
responseArray.push({
tag,
result
});
handleResponse();
};
const testB = async () => {
const tag = `${Date.now()}-testB`;
requestArray.push({
tag,
callback: result => {
console.log("执行 tagB 的回调");
changeResult(result);
}
});
const result = await ajaxB();
responseArray.push({
tag,
result
});
handleResponse();
};
buttonA.onclick = testA;
buttonB.onclick = testB;