To solve this problem you first have to know when a candle is going to close, to find out we can check the k.x value of the data returned by the kline websocket, when the k.x value is true it means that the candle is about to close and not that has already closed, this value is set to true at 999 milliseconds of the current candle, that is, the candle has not yet closed but in the next call to onmessage event it must already be closed, so the following code may cause that when requesting the last 3 candles only return 2 in some occasions as you can see in the image
socket.onmessage = e => {
data = JSON.parse(e.data)
if (data.k.x) klines(symbol, interval, limit, startTime, endTime, data => console.log(data))
}
To fix this problem we have to cause a delay so that the request is executed in the next onmessage event that is executed after k.x is set to true which we can do in two ways either by using a global flag or by using a timer as follows
candleClosed = false`
socket.onmessage = e => {
data = JSON.parse(e.data)
if(candleClosed) {
candleClosed = false
klines(symbol, interval, limit, startTime, endTime, data => console.log(data))
}
if (data.k.x) candleClosed = true
Or
socket.onmessage = e => {
data = JSON.parse(e.data)
if (data.k.x) setTimeout(klines(symbol, interval, limit, startTime, endTime, data => console.log(data)), 2000)
}
Which solves the problem as can be seen in the image
Finally, if the only thing you want is to obtain the last three candles, you only need to set the limit of the query to 3 and you avoid having to calculate the startTime (because I suppose you are calculating it or at least saving it in an array), from so the request should be the following
https://api.binance.com/api/v3/klines?symbol=XXXX&interval=1m&limit=3