Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async/Await #99

Open
rogerxu opened this issue Feb 13, 2017 · 5 comments
Open

Async/Await #99

rogerxu opened this issue Feb 13, 2017 · 5 comments

Comments

@rogerxu
Copy link
Owner

rogerxu commented Feb 13, 2017

@rogerxu
Copy link
Owner Author

rogerxu commented Feb 13, 2017

async 函数 - ECMAScript 6入门

  • Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。
  • co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
  • 返回值是 Promise
var asyncReadFile = async function () {
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};
async function chainAnimationsAsync(elem, animations) {
  var ret = null;
  try {
    for (var anim of animations) {
      ret = await anim(elem);
    }
  } catch(e) {
    /* 忽略错误,继续执行 */
  }
  return ret;
}

@rogerxu rogerxu changed the title Async functions Async/Await May 9, 2017
@rogerxu
Copy link
Owner Author

rogerxu commented Dec 26, 2017

Async Iterators and Generators

Async Iterators

for await of

The for-of loop will get its iterator by calling thing[Symbol.iterator]. Whereas the for-await loop will get its iterator by calling asyncThing[Symbol.asyncIterator].

async function example() {
  // Regular iterator:
  for (const item of thing) {
    // …
  }

  // Async iterator:
  for await (const item of asyncThing) {
    // …
  }
}

Bad

async function getResponseSize(url) {
  const response = await fetch(url);
  const reader = response.body.getReader();
  let total = 0;

  while (true) {
    const {done, value} = await reader.read();
    if (done) return total;
    total += value.length;
  }
}

Good

async function getResponseSize(url) {
  const response = await fetch(url);
  let total = 0;

  for await (const chunk of response.body) {
    total += chunk.length;
  }
  return total;
}

Async Generators

Creating your own async iterator

// Note the * after "function"
async function* asyncRandomNumbers() {
  // This is a web service that returns a random number
  const url = 'https://www.random.org/decimal-fractions/?num=1&dec=10&col=1&format=plain&rnd=new';

  while (true) {
    const response = await fetch(url);
    const text = await response.text();
    yield Number(text);
  }
}
async function* streamAsyncIterator(stream) {
  // Get a lock on the stream
  const reader = stream.getReader();

  try {
    while (true) {
      // Read from the stream
      const {done, value} = await reader.read();
      // Exit if we're done
      if (done) return;
      // Else yield the chunk
      yield value;
    }
  } finally {
    reader.releaseLock();
  }
}

async function example() {
  const response = await fetch(url);

  for await (const chunk of streamAsyncIterator(response.body)) {
    // …
  }
}

@rogerxu
Copy link
Owner Author

rogerxu commented May 28, 2018

Getting Started with Async/Await – freeCodeCamp

Async Functions Return a Promise

When you create a function with the async keyword that function will always return a Promise.

// here is an async function
async function getNumber() {
  return 4; // actually returns a Promise
}

// the same function using promises
function getNumber() {
  return Promise.resolve(4);
}

Async Functions are the only Place where you can use Await

Await lets you pause the execution of an async function until it receives the results of a promise. This lets you write async code that reads in the order that it’s executed.

// async function to show user data
async function displayUserData() {
  let me = await fetch('/users/me');
  console.log(me);
}

// promise-based equivalent
function displayUserData() {
  return fetch('/users/me').then(function(me) {
    console.log(me);
  });
}

Error Handling in Async Functions

Because an async function is a Promise, when you throw inside of an async function it’s swallowed up and returned as a rejected Promise.

// basic error handling with async functions
async function getData(param) {
  if (isBad(param)) {
    throw new Error("this is a bad param");
  }
  // ...
}

// basic promise-based error handling example
function getData(param) {
  if (isBad(param)) {
    return Promise.reject(new Error("this is a bad param"))
  }
  // ...
}

If you are using await to call the Promise you can wrap it in try/catch or you’ll need to add a catch handler to the returned Promise.

// rely on try/catch around the awaited Promise
async function doSomething() {
  try { 
    let data = await getData();
  } catch (err) {
    console.error(err);
  }
}

// add a catch handler
function doSomething() {
  return getData().catch(err => {
    console.error(err);
  });
}

Example

// catch any errors in the promise and either forward them to next(err) or ignore them
const catchErrors = fn => (req, res, next) => fn(req, res, next).catch(next);
const ignoreErrors = fn => (req, res, next) => fn(req, res, next).catch(() => next());

const catchErrors = function(fn) {
  return function(req, res, next) {
    return fn(req, res, next).catch(next);
  };
};

// wrap my routes in those helpers functions to get error handling
app.get('/sendMoney/:amount', catchErrors(sendMoney));

// use our ignoreErrors helper to ignore any errors in the logging middleware
app.get('/doSomethingElse', ignoreErrors(logSomething), doSomethingElse);

// controller method can throw errors knowing router will pick it up
export async function sendMoney(req, res, next) {
  if (!req.param.amount) {
     throw new Error('You need to provide an amount!');
  }

  await Money.sendPayment(amount); // no try/catch needed
  res.send(`You just sent ${amount}`);
}

// basic async logging middleware
export async function logSomething(req, res, next) {
  // ...
  throw new Error('Something went wrong with your logging');
  // ...
}

@rogerxu
Copy link
Owner Author

rogerxu commented May 28, 2018

How to escape async/await hell – freeCodeCamp

async function orderItems() {
  const items = await getCartItems();    // async call
  const noOfItems = items.length;
  for (let i = 0; i < noOfItems; i++) {
    await sendRequest(items[i]);    // async call
  }
}

In this case, the for loop has to wait for the sendRequest() function to complete before continuing the next iteration. However, we don’t actually need to wait. We want to send all the requests as quickly as possible and then we can wait for all of them to complete.

async function orderItems() {
  const items = await getCartItems(); // async call
  const promises = items.map(item => sendRequest(item));
  await Promise.all(promises); // async call
}

@rogerxu rogerxu mentioned this issue Mar 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant