프런트엔드 Promise의 몇 가지 일반적인 애플리케이션 시나리오

hzc
풀어 주다: 2020-06-15 10:08:31
앞으로
4297명이 탐색했습니다.

이 기사에서는 ES6 Promise 사용을 기반으로 프로젝트 개발에서 Promise의 일반적인 적용 시나리오를 요약합니다. 물론 Promise가 유일한 선택은 아닐 수도 있지만 자격을 갖춘 프런트 엔드 개발자로서 우리는 이를 이해해야 합니다.

Promise.all


구문: ​​Promise.all(반복 가능)

매개변수: 배열과 같은 반복 가능한 객체.

반환 값:

  • 전달된 iterable이 비어 있으면 해결된 Promise입니다.

Promise.all([]).then(res=>{
    console.log(res)//[]
})
로그인 후 복사
  • Promise는 비동기식으로 해결됩니다(전달된 Iterable에 Promise가 포함되지 않은 경우). 이 경우 Google Chrome 58은 해결된 Promise를 반환합니다.

Promise.all([1,2,3]).then(res=>{
    console.log(res)//[1,2,3]
})
로그인 후 복사
  • 주어진 iterable의 모든 Promise가 해결되거나 모든 Promise가 거부되면 이 반환된 Promise는 비동기적으로(스택이 비어 있을 때) 해결/거부됩니다.

    1. 주어진 경우 모든 Promise는 주어진 iterable이 해결되었습니다

let promise1 = new Promise((resolve,reject)=>{
    resolve(1)
})
let promise2 = new Promise((resolve,reject)=>{
    resolve(2)
})

Promise.all([promise1,promise2,3]).then(res=>{
    console.log(res)//[1,2,3]
})
로그인 후 복사

2. 주어진 iterable의 약속이 거부된 경우

let promise1 = new Promise((resolve,reject)=>{
    resolve(1)
})
let promise2 = new Promise((resolve,reject)=>{
    reject(2)
})

Promise.all([promise1,promise2,3]).then(res=>{
    console.log(res)
}).catch(err=>{
    console.log(err)//2
})
로그인 후 복사

설명:

이 방법은 여러 약속의 결과를 집계하는 데 유용합니다. ES6에서는 여러 Promise.all 비동기 요청이 가능합니다. 병렬로 작동:

1. 모든 결과가 성공적으로 반환되면 요청 순서에 성공이 반환됩니다.

2. 실패 메서드가 있는 경우

응용 시나리오 1: 다중 요청 결과; 함께 병합됩니다

상세 설명: 한 페이지에 여러 요청이 있습니다. 렌더링을 함께 처리하기 전에 모든 요청이 데이터를 반환해야 합니다.

생각: 동시 요청이 있는 경우 각 요청의 로딩 상태를 별도로 설정해야 합니다. 여러 개의 로딩이 있는 경우, 요청에 따른 데이터 반환 속도에 따라 페이지에 표시되는 내용이 달라질 수 있습니다. 이는 사용자 경험을 개선하기 위해 구체적으로 반영됩니다. 모든 요청이 반환된 후에는 함께 렌더링됩니다. 이때 요청의 별도 로딩 설정을 끄고 Promise.all을 통해 요청 결과를 처음부터 끝까지 한 번만 로딩하도록 설정했습니다. .

//1.获取轮播数据列表
function getBannerList(){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('轮播数据')
        },300)
    })
}

//2.获取店铺列表
function getStoreList(){
   return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('店铺数据')
        },500)
    })
}

//3.获取分类列表
function getCategoryList(){
   return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('分类数据')
        },700)
    })
}

function initLoad(){
    // loading.show() //加载loading
    Promise.all([getBannerList(),getStoreList(),getCategoryList()]).then(res=>{
        console.log(res)
        // loading.hide() //关闭loading
    }).catch(err=>{
        console.log(err)
        // loading.hide()//关闭loading
    })
}
//数据初始化    
initLoad()
로그인 후 복사

애플리케이션 시나리오 2: 요청 결과 병합 및 오류 처리

설명: 요청의 데이터 렌더링 및 오류 처리 로직을 별도로 처리해야 합니다. 요청이 여러 개인 경우 이를 여러 개 작성해야 합니다. place

생각: 여러 요청을 병합할 수 있나요? 일부 요청이 실패하더라도 한 곳에서 데이터와 오류 로직만 처리하면 됩니다.

//1.获取轮播图数据列表
function getBannerList(){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            // resolve('轮播图数据')
            reject('获取轮播图数据失败啦')
        },300)
    })
}

//2.获取店铺列表
function getStoreList(){
   return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('店铺数据')
        },500)
    })
}

//3.获取分类列表
function getCategoryList(){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('分类数据')
        },700)
    })
}

function initLoad(){
    // loading.show()
    Promise.all([
        getBannerList().catch(err=>err),
        getStoreList().catch(err=>err),
        getCategoryList().catch(err=>err)
    ]).then(res=>{
        console.log(res) // ["获取轮播图数据失败啦", "店铺数据", "分类数据"]
        
        if(res[0] == '轮播图数据'){
            //渲染
        }else{
            //获取 轮播图数据 失败的逻辑
        }
        if(res[1] == '店铺数据'){
            //渲染
        }else{
            //获取 店铺列表数据 失败的逻辑
        }
        if(res[2] == '分类数据'){
            //渲染
        }else{
             //获取 分类列表数据 失败的逻辑
        }
        
        // loading.hide()
    })
}

initLoad()
로그인 후 복사

때때로 페이지가 중단되는 경우가 있습니다. 인터페이스 예외로 인해 또는 단지 중요하지 않은 인터페이스 때문에 중단되는 것일 수도 있습니다. 그렇다면 인터페이스가 중단되어 전체 페이지에 데이터가 표시되지 않는 이유는 무엇입니까? Promise.all은 매개변수의 약속이 실패하고(거부됨) 이 인스턴스의 콜백이 실패하면(거부), then 메서드 콜백이 더 이상 실행되지 않음을 알려줍니다. 위의 사용 사례는 이 문제를 해결할 수 있습니다

애플리케이션 시나리오 3: 확인 여러 요청의 결과가 조건을 충족합니까? 설명: WeChat 애플릿 프로젝트에서 양식의 입력 내용은 클라우드 기능에 의해 작성된 메소드가 호출됩니다. 모든 검증을 통과하면 정상적인 제출이 가능합니다. 매개변수: 배열과 같은 반복 가능하고 사용 가능한 반복 가능한 객체입니다. 반복 가능합니다.

반환 값

: Promise.race(iterable) 메서드는 반복자의 특정 Promise가 해결되거나 거부되면 Promise를 반환합니다.

Descriptionrace 함수는 Promise를 반환합니다. 처음 통과된 약속과 동일한 방식으로 이행됩니다. 둘 중 어느 것이 먼저 완료되었는지에 따라 해결(해결)되거나 실패(거부)될 수 있습니다.


전달된 반복이 비어 있으면 반환된 Promise는 영원히 기다립니다.

반복에 하나 이상의 약속되지 않은 값 및/또는 해결/거부된 약속이 포함된 경우 Promise.race는 반복에서 발견된 첫 번째 값으로 확인됩니다.

응용 시나리오 1: 이미지 요청 시간 초과

function verify1(content){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve(true)
        },200)
    })
}

function verify2(content){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve(true)
        },700)
    })
}

function verify3(content){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve(true)
        },300)
    })
}



Promise.all([verify1('校验字段1的内容'),verify2('校验字段2的内容'),verify3('校验字段3的内容')]).then(result=>{
    console.log(result)//[true, true, true]

    let verifyResult = result.every(item=>item)
    //验证结果
    console.log(verifyResult?'通过验证':'未通过验证')// 通过验证
}).catch(err=>{
    console.log(err)
})
로그인 후 복사

응용 시나리오 2: 요청 시간 초과 프롬프트

설명: 때로는 뉴스를 1초 동안 탐색하다가 엘리베이터에 들어간 후 다음 1초 동안 모바일 페이지가 "Poor network"라는 메시지가 표시됩니다

//请求某个图片资源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
           resolve(img);
        }
        //img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg"; 正确的
        img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg1";
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});
로그인 후 복사

Promise.prototype.then

응용 시나리오 1: 다음 요청은 이전 요청의 결과에 따라 달라집니다

描述:类似微信小程序的登录,首先需要 执行微信小程序的 登录 wx.login 返回了code,然后调用后端写的登录接口,传入 code ,然后返回 token ,然后每次的请求都必须携带 token,即下一次的请求依赖上一次请求返回的数据

function A(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('B依赖的数据')
        },300)
    })
}
function B(prams){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(prams + 'C依赖的数据')
        },500)
    })
}
function C(prams){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(prams)
        },1000)
    })
}

//我们期望的是走 try ,由于A B C模拟的请求中都是没有reject,用 try catch 捕获错误
try{
    A().then( res=>B(res) ).then( res=>C(res) ).then( res=>{
        console.log(res)//B依赖的数据C依赖的数据
    })   
} catch(e){
    
}
로그인 후 복사

应用场景2:中间件功能使用

描述:接口返回的数据量比较大,在一个then 里面处理 显得臃肿,多个渲染数据分别给个then,让其各司其职

//模拟后端返回的数据

let result = {
    bannerList:[
        {img:'轮播图地址'}
    //...
    ],
    storeList:[
        {name:'店铺列表'}
    //...
    ],
    categoryList:[
        {name:'分类列表'}
    //...
    ],
    //...
}

function getInfo(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(result)
        },500)
    })
}

getInfo().then(res=>{

    let { bannerList } = res
    //渲染轮播图
    console.log(bannerList)
    return res
}).then(res=>{
    
    let { storeList } = res
    //渲染店铺列表
    console.log(storeList)
    return res
}).then(res=>{
    let { categoryList } = res
    console.log(categoryList)
    //渲染分类列表
    
    return res
})
로그인 후 복사

推荐教程:《JS教程

위 내용은 프런트엔드 Promise의 몇 가지 일반적인 애플리케이션 시나리오의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!