Skip to content

ES6 语法中的 async 和 await #2

Description

@penouc

ES6 语法中的 async 和 await

async 函数用法

 async function f () {
	return 1
}
f.then(i => i)

 async function f () {
	return Promise.resolve(1)
}
f.then(i => i)

由以上两例可以知道 ,async 函数中 return 后如果返回的是 promise 对象,那么返回的就直接是那个 promise 对象,如果是非 promise 对象,那么 async 函数会将其包裹为一个 promise 对象。

await 语句的使用

await 必须在 async 函数中使用

 async function f (){
   console.time('value');
    let value = await  new Promise((resolve, reject) => {                     
      setTimeout( () => {resolve(1000);} , 1000)
    })
    console.log(value);
 console.timeEnd('value');
  }

使用了 await 之后会将 promise 包裹的数据解构,注意 await 必须在 async 函数中使用,Promise.resolve 使用 await 会导致报错。

使用的例子

async function  showAvatar(){
  // read our JSON
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // read github user
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // show the avatar
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // wait 3 seconds
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
 }

注意

  • 不能在没有 async 函数包裹的情况下,使用 await 语句
  • 所有的 thenable 的对象都可以使用 await 函数

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // resolve with this.num*2 after 1000ms
    setTimeout(() => resolve(this.num * 2), 1000); // (*)
  }
};

async function f() {
  // waits for 1 second, then result becomes 2
  let result = await new Thenable(1);
  alert(result);
}

f();
  • 可以在 class 类中使用 async 函数

class Waiter {
  async wait() {
    return await Promise.resolve(1);
  }
}

new Waiter()
  .wait()
  .then(alert); // 1

Error handling

下面这些代码 介绍了如何在 async 函数中抛出异常:


 async function f() {
  await Promise.reject(new Error("Whoops!"));
}

这个和下面的意义是一样的


async function f() {
  throw new Error("Whoops!");
}

还有下面


 async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}

f();

自己的一些使用体会

下面两种用法, 为什么上面的有效,下面的无效

  • 第一种

	   async function getTraces() {
	    let userPromises = [];
	    for (let index = 0; index < users.length; index++) {
	      const user = users[index];
	      userPromises[index] = await fetchGet(
	        'ip:port/' +
	          user.dscode +
	          '&userid=' +
	          user.userId +
	          '&' +
	          TIME
	      ).then(res => {
	        return res.json();
	      });
	    }
	
	    return userPromises;
	  }
  • 第二种

    let userPromises = [];
    
    userPromises = users.map(user => {
        return await fetchGet(
        'ip:port/' +
            user.dscode +
            '&userid=' +
            user.userId +
            '&' +
            TIME
        ).then(res => {
        return res.json();
        });
    })

因为第二个函数中 await 被包裹在了map 的匿名函数中导致不能使用

如何才能保证异步一个个执行await 语句呢

每一个 await 函数后面都传递的是未触发的 Promise, 并且保证每一个 resolve 都写在该函数中的异步流中


Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions