Problem Description:

  • Network requests are asynchronous if usedforLoop, make a lot of data requests, return data, probably not in the order the user entered.

Solutions:

  • I can use it herePromise.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.allHow is the internal implementation of the order, let’s dig a digPromise.allInside secrets
  • Put it on first, by handPromise.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 aboveforEachMethod, the first argumentpromiseThe current object to traverse, the lastindexIs 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 aboveforEachMethod, the first argumentpromiseThe current object to traverse, the lastindexIs the key? Tell meindexIs 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 didindedAlso 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:
  1. You need to determine whether the current object being traversed isPromiseType, however, can be usedPromise.resolve()This ensures that the current object isPromiseType.
  2. You need to useindexRes [index] = data
  3. You need to set onecountUsed to determine whether all data has been retrieved.