如何在多个异步请求中使用js async / await

我正在使用Angular 7,现在有一个方法(Angular Guard Canactivate)包含一些嵌套的http调用方法,所有嵌套的http调用完成后,我需要返回数据。

如下面的代码所示,只有在getcurrentUser()完成之后,才在canactivate()中返回结果,而现在,由于getcurrentUser()尚未完成,它总是返回false。

export class AuthGuard implements  Canactivate{


  constructor(private commonService: CommonService) {
  }

  async canactivate(next: activatedRoutesnapshot,state: RouterStatesnapshot): Promise<boolean> {
    console.log('======');
    await this.getcurrentUser();
    return this.hasaccess;
  }

  hasaccess: boolean = false;

  async getcurrentUser(){
    await this.commonService.getToken().subscribe(token => {
      this.commonService.getcurrentUser(param,token).subscribe(o => {
        if(o.success){

          this.hasaccess = true;

        }else {
            window.location.href = '/forbidden.html';
          }
      },error => {
        console.log(error);
      });
    });
    console.log("async");
  }
}

您可以看到有两种异步方法A,B应该等待,而A,B不是并行的,我检查了关于Promise和async / await的文档,没有找到解决方法。

由于应始终在异步之后等待,所有异步http调用完成后,如何使canactivate()返回结果?

+++更新

this.commonService.getToken()this.commonService.getcurrentUser(param,token)是http呼叫(HttpClient),我尝试了很多解决方案,但没有结果。

hourace 回答:如何在多个异步请求中使用js async / await

您正在寻找Promise.all()方法。

,

您可以结合使用 GoogleMap( markers: _markers,mapType: MapType.normal,initialCameraPosition: CameraPosition( target: latLng,zoom: 14.4746,),onMapCreated: (GoogleMapController controller) { _controller.complete(controller); },floatingActionButton: FloatingActionButton.extended( onPressed: _goToTheLake,label: Text('To the lake!'),icon: Icon(Icons.directions_boat),Future<void> _goToTheLake() async { final GoogleMapController controller = await _controller.future; controller.animateCamera(CameraUpdate.newLatLng( LatLng(20.008751,73.780037))); } async await。这样,您可以等待所有异步网络请求,并在所有请求完成后执行一些操作。

Promise.all接受一组诺言并将其包装为一个诺言。而且我们已经知道一些处理单个诺言的不错的语法。我们可以等待。

为您的理解,请看以下代码示例:

Promise.all()

我在本文中引用了此示例,可以帮助您找出解决方案

How to use async/await with map and Promise.all

更新: 对于您的用例,您可以这样使用:

let films = await Promise.all(
  characterResponseJson.films.map(async filmUrl => {
    let filmResponse = await fetch(filmUrl)
    return filmResponse.json()
  })
)
console.log(films)
,

asyncawait建立在承诺之上。 Promise是javascript中的一个特殊对象,广泛用于避免回调地狱

在使用trycatch时,async await块也很重要,因为如果API失败,我们也需要处理错误。

hasAccess: boolean;
canActivate(next: ActivatedRouteSnapshot,state: RouterStateSnapshot): Promise < boolean > {
    this.getCurrentUser();
    return this.hasAccess;
}

async getCurrentUser() {
    try {
        const output1 = await Promise.resolve(fetch(urlOfToken).then(res => res.json())) // if GET call,if POST you can postData('',{})
        const currentUser = await this.postData(
            `URL fetching current user`,{
                token: `access token from object ${output} `,param: 'any other param'
            }
        );
        // Check in currentUser Object whether response contains user or not
        // If user exists set this.hasAccess = true;
        // IF not set this.hasAccess = false;
    } catch (error) {
        // Error Handling
        console.log(error);
    }
}
// Courtesy MDN
async postData(url = '',data = {}) {
    // Default options are marked with *
    const response = await fetch(url,{
        method: 'POST',// *GET,POST,PUT,DELETE,etc.
        mode: 'cors',// no-cors,*cors,same-origin
        cache: 'no-cache',// *default,no-cache,reload,force-cache,only-if-cached
        credentials: 'same-origin',// include,*same-origin,omit
        headers: {
            'Content-Type': 'application/json'
            // 'Content-Type': 'application/x-www-form-urlencoded',},redirect: 'follow',// manual,*follow,error
        referrer: 'no-referrer',// no-referrer,*client
        body: JSON.stringify(data) // body data type must match "Content-Type" header
    });
    return await response.json(); // parses JSON response into native JavaScript objects
}

有关如何将promisesasyncawait一起使用的更多参考。还有关于如何进行并行,序列和竞赛API调用

const urls = [
    'https://jsonplaceholder.typicode.com/users','https://jsonplaceholder.typicode.com/albums','https://jsonplaceholder.typicode.com/posts'
];

// BASIC

Promise
    .all(urls.map(url => {
        return fetch(url).then(res => res.json())
    }))
    .then((results) => {
        console.log(results[0]);
        console.log(results[1]);
        console.log(results[2]);
    })
    .catch(() => console.log('error!'));


// async await
// built atop of promises
// benefit is it is easier to make code read easier nothing more promises can get job done actually
const getData = async function () {
    try {
        const [users,albums,posts] = await Promise.all(urls.map(url => {
            return fetch(url).then(res => res.json())
        }));
        console.log('users',users);
        console.log('albums',albums);
        console.log('posts',posts);
    } catch (error) {
        console.log('Oops!');
    }
}

// for await of
const getData2 = async function () {
    const arrayOfPromises = await urls.map(url => fetch(url));
    for await (let request of arrayOfPromises) {
        const response = await request.json();
        console.log(response);
    }
}


const a = () => promisify('a',100); // I am making it asynchronous here ; Can be API call or any asynchronus task
const b = () => promisify('b',1000);// I am making it asynchronous here ; Can be API call or any asynchronus task
const c = () => promisify('c',5000);// I am making it asynchronous here ; Can be API call or any asynchronus task

const promisify = (item,delay) =>
    new Promise((resolve) =>
        setTimeout(() =>
            resolve(item),delay));

// Parallel

async function parallel() {
    const [output1,output2,output3] = await Promise.all([a(),b(),c()]);
    return `parallel done right: ${output1},${output2},${output3}`;
}

// race

async function race() {
    const output1 = await Promise.race([a(),c()]);
    return `race done right: ${output1}`;
}

// sequence

async function sequence() {
    const output1 = await a();
    const output2 = await b();
    const output3 = await c();
    return `sequenece done right: ${output1},${output3}`;
}


parallel().then(console.log);
race().then(console.log);
sequence().then(console.log);
,

参考上面的答案和其他人的帮助,我更新了代码,现在可以使用了。 我的更新是在 getToken() getUser()中使用new Promise(),而不是awaitPromise具有状态(待处理已解决已被拒绝),一旦状态更改,无论如何Promise的状态都不会更改更改为 reloved ,它不会被更改,Promise将返回其值,否则,如果更改为 reject ,它将出错。

按如下所示附加我的更新代码:

可以激活

async canActivate(next: ActivatedRouteSnapshot,state: RouterStateSnapshot): Promise<boolean> {
    console.log('======');
    let token = await this.getToken();
    // let hasAccess = await this.getUser(token);
    return await this.getUser(token);
  }

getToken() getUser()

// return a Promise object and resolve(token)
getToken(){
    return new Promise((resolve,reject)=>{
      this.commonService.getToken().subscribe(token=>{
        resolve(token)
      })
    })
  }

  getUser(token: any) {
    return new Promise<boolean>((resolve,reject) => {
      this.commonService.getCurrentUser(param,token).subscribe(o => {
        if(o.success){

          hasAccess = true;
        }else {
          window.location.href = '/forbidden.html';
        }
        resolve(hasAccess);
      },error => {
        console.log(error);
        resolve(hasAccess);
      });
    })
  }

我对 async / await Promise 不太熟悉,因此欢迎更正错误。

本文链接:https://www.f2er.com/3161696.html

大家都在问