Problem Description:
- Network requests are asynchronous if used
for
Loop, make a lot of data requests, return data, probably not in the order the user entered.
Solutions:
- I can use it here
Promise.all()
Method implementation, asynchronous network request, return data is also in order.
export default functionlaodFiles(dataFiles) {
return new Promise(((resolve, reject) = > {
// promise.all guarantees that the output order is the same as the input order
Promise.all(dataFiles.map(dataFile= > {
axios.get(dataFile.url).then(res= > ({date: new Date(res), data: res}))
})).then(data= > {
resolve(data)
}).catch(err= > {
reject(err)
})
}))
}
Copy the code
Realize the principle of
Promise.all
How is the internal implementation of the order, let’s dig a digPromise.all
Inside secrets- Put it on first, by hand
Promise.all()
Correct way to write:
function PromiseAll(promises) {
return new Promise((resolve, reject) = > {
if (!Array.isArray(promises)) {
return reject(new Error('The argument passed must be in array format.'))}let res = []
let count;
promises.forEach((promise, index) = > {
// We need to check if the current iterated promise is of the promise type, but we don't. Think about why.
Promise.resolve(promise).then(data= > {
// Note 1: index is used to ensure sequential storage
res[index] = data
count++
// Note that point 2: count is used to ensure that all the desired data is retrieved
if(count === promises.length) {
resolve(res)
}
}, err= > {
}).catch(err= > {
return reject(err)
})
})
})
}
Copy the code
Incorrect way of writing:
- Of the code above
forEach
Method, the first argumentpromise
The current object to traverse, the lastindex
Is the key, someone might process the result by writing it like this:
let count =0
let res = []
let length= promises.length
promises.forEach(promise= > {
Promise.resolve(promise).then(data= > {
res.push(data)
// Determine whether the current result array length is the length of the array passed in
if(res.length === length) resolve(res)
})
})
Copy the code
-
But there’s a problem with using the length of the returned result like this, and that is, the result data inside is not in order, and as soon as the result is returned, you push it inside, and maybe the first result that is returned, is not the first parameter that is passed in, it could be the third or whatever.
Incorrect:
- Of the code above
forEach
Method, the first argumentpromise
The current object to traverse, the lastindex
Is the key? Tell meindex
Is the key, so I’ll just put it on, and then, maybe someone will process the result and write something like this:
let count =0
let res = []
let length= promises.length
promises.forEach((promise, index) = > {
Promise.resolve(promise).then(data= > {
// 1. Put the data into the array according to the corresponding index
res[index] = data
// 2. Check whether the current array length is the size of the array passed in
if(res.length === length) resolve(res)
})
})
Copy the code
- Well, you might say, I did
inded
Also in order, I write like this is no problem! But! If you think about it, the first one that comes back is the last oneindex
, that directly fills the array, and the result is:[undefined,undefined,undefined,undefined,......, data]
This must be wrong, then all the data before is empty.
conclusion
- Before using the good tools created by predecessors, also think about the principles, so that you can learn some knowledge and skills from the predecessors.
- Two points to note here:
- You need to determine whether the current object being traversed is
Promise
Type, however, can be usedPromise.resolve()
This ensures that the current object isPromise
Type. - You need to use
index
Res [index] = data - You need to set one
count
Used to determine whether all data has been retrieved.