列举三类
第一类:很多个异步,依次执行,要有顺序
- 方法一 使用加载事件特性(img的src变化,load事件执行)
/**
* 图片加载
*/
function getImage(num){
let img = new Image()
img.src = `./image/${num}.png`
img.num = num
img.arr = []
img.addEventListener('load',loadHandle)
}
function loadHandle(e){
let cloneImg = e.currentTarget.cloneNode()
this.arr.push(cloneImg)
this.num++
if(num > 59) return this.arr
that.src = `./image/${this.num}.png`
}
/**
* 图片加载
*/
function getImage2(num){
return new Promise((resolve,reject)=>{
let img = new Image()
img.src = `./image/${num}.png`
img.onload = function(){
resolve(img)
}
})
}
function main(total){
let arr = []
for(let i = 0; i < total; i++){
let img = getImage2(i)
arr.push(img)
}
if(arr.length === 56){
Promise.all(arr).then(list=>{
console.log(list)
})
}
}
/**
* 图片加载
*/
function getImage1(num){
return new Promise((resolve,reject)=>{
let img = new Image()
img.src = `./image/${num}.png`
img.onload = function(){
resolve(img)
}
})
}
async function main(total){
let arr = []
for(let i = 0; i < total; i++){
let img = await getImage(i)
arr.push(img)
}
}
/**
* 音频加载
*/
function loadFile(item){
return new Promise((resolve,reject)=>{
let { name, url, fileId, size } = item
let temp = new Audio(url)
temp.onloadedmetadata = function(){
resolve({
audioName: name.slice(0,40),
audioUrl: url,
fileId: fileId,
fileSize: size,
duration: temp.duration
})
}
temp.onerror = function(){ // 没有监听error事件,加载失败后,会卡住不继续执行
resolve({
audioName: name.slice(0,40),
audioUrl: url,
fileId: fileId,
fileSize: size,
duration: temp.duration || 0
})
}
})
}
//上传腾讯云成功的回调
const onChange =async (res) => {
let params = [], fileList = Array.prototype.slice.call(res)
for(let i = 0; i < fileList.length; i++){
let result = await loadFile(fileList[i])
params.push(result)
}
addAudio({list: params}).then(res=>{ // 调用后端接口
if(res && res.code === 100){
message.success('上传成功')
updataList() // 更新列表
}
})
}
第二类:很多个异步,只要最后所有的执行结果
/**
* Promise的静态方法all的重构(数组中所有的promise执行结束后,才会返回结果)
* @param {*} list
* @returns
*/
PromiseSelf.all = function(list){
return new PromiseSelf((resolve,reject)=>{
let done = gen(resolve,list.length)
list.forEach((item,index)=>{
item.then(value=>{
done(index,value)
})
})
})
}
function gen(resolve,length){
let values = []
return function(i,value){
values[i] = value
if(i === length - 1){
resolve(values)
}
}
}
第三类:很多个异步,只要最后一次的执行结果(适用场景: 搜索时,每次输入要调用接口,接口得同步)
constructor(props){
super(props)
this.state = {
searchResult: ''
}
this.queueList = []
}
handleSearch(type){ //文本改变
return async (value)=>{
this.pushQueue(value, []); // 将每次输入内容放置到数组中
let result = await this.handleSearchAPI(type, value); // 等待每次请求
this.queueList.forEach(element => { // 遍历数组,将当前接口返回的数据准确放置在对应的输入内容上
if(element.key == value){ element.result = result; }
});
let searchResult = this.searchQueue[this.searchQueue.length - 1].result; // 取数组中最后一项结果展示
this.setState({ ...searchResult, });
}
}
pushQueue(key, result){
this.queueList.push({key, result});
}
handleSearchAPI(type, value, scroll = 0){ //请求接口优化
return new Promise((resolve, reject) =>{
trainCampSchool({ // 接口请求
word:value || '',
pageNum: this.searchPageNum,
pageSize: this.searchPageSize,
}).then(res=>{
let schoolDataList=this.state.school.concat(res.data.dataList)
resolve({
school: schoolDataList
scrollFlag:true
})
}).catch(err =>{
reject(err);
})
} )
}
<Select
showSearch
style={{ width: 136 }}
placeholder="学校名称"
allowClear={true}
filterOption={false}
value = {this.state.schoolName }
onChange={this.handleChange('school')}
onFocus={this.handleFocus('school')}
onSearch={this.handleSearch('school')}
onPopupScroll={this.handlePopupScroll('school')}
getPopupContainer={triggerNode => triggerNode.parentElement}
>
{
this.state.school?.map((item)=>
<Option value={item.schoolId} key={item.schoolId}>{item.fullName}</Option>
)
}
</Select>