jackieli123723 / jackieli123723.github.io

✅lilidong 个人博客
9 stars 0 forks source link

async-await #1

Open jackieli123723 opened 7 years ago

jackieli123723 commented 7 years ago

1. async/await 函数是什么?

一句话,async 函数就是 Generator 函数的语法糖。

var asyncReadFile = async function (){
    var f1 = await readFile('/etc/fstab');
    var f2 = await readFile('/etc/shells');
    console.log(f1.toString());
    console.log(f2.toString());
};

2. async 函数的优点

(1)内置执行器。 async 函数的执行,与普通函数一模一样,只要一行。var result = asyncReadFile();

(2)更好的语义。 async 和 await,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。

(3)更广的适用性。 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

3. async 函数的实现

async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args){
      // ...
}

async 函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel 和 regenerator 都已经支持,转码后就能使用。

4. async 函数的用法

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。 下面是一个例子。

async function getStockPriceByName(name) {
    var symbol = await getStockSymbol(name);
    var stockPrice = await getStockPrice(symbol);
    return stockPrice;
}

getStockPriceByName('goog').then(function (result){
    console.log(result);
});

下面的例子,指定多少毫秒后输出一个值。

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value)
}
asyncPrint('hello world', 50);
上面代码指定50毫秒以后,输出"hello world"。

5. 注意点

await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。

async function myFunction() {
  try {
    await somethingThatReturnsAPromise();
  } catch (err) {
    console.log(err);
  }
}

// 另一种写法

async function myFunction() {
  await somethingThatReturnsAPromise().catch(function (err){
    console.log(err);
  };
}
await 命令只能用在 async 函数之中,如果用在普通函数,就会报错。
async function dbFuc(db) {
  let docs = [{}, {}, {}];
  // 报错
  docs.forEach(function (doc) {
    await db.post(doc);
  });
}
上面代码会报错,因为 await 用在普通函数之中了。但是,如果将 forEach 方法的参数改成 async 函数,也有问题。
async function dbFuc(db) {
  let docs = [{}, {}, {}];

  // 可能得到错误结果
  docs.forEach(async function (doc) {
    await db.post(doc);
  });
}

上面代码可能不会正常工作,原因是这时三个 db.post 操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for 循环。

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  for (let doc of docs) {
    await db.post(doc);
  }
}

如果确实希望多个请求并发执行,可以使用 Promise.all 方法。

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);
  console.log(results);
}
// 或者使用下面的写法

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = [];
  for (let promise of promises) {
    results.push(await promise);
  }
  console.log(results);
}

可以参考基于async-await写的一个爬虫例子: https://github.com/lincenying/async-await

jackieli123723 commented 7 years ago
const users = [
  { name: 'John', homepage: 'http://john.name' },
  { name: 'Maria', homepage: 'http://maria.name' },
];

const pageExists = url => new Promise(resolve =>
  setTimeout(() => resolve(true), 1000)
);

async function main() {
  const result = await Promise.all(
    users.map(async user =>
      await Object.assign({}, user, {
        verified: await pageExists(user.homepage)
      })
    )
  );

  console.log(result);
}

main();

另外一种

function a(){
  return new Promise ( (resolve,reject) => {
    setTimeout( () => {
      resolve(100)
      //reject('this is error') //此次模拟错误
    },2000)
  });

};

var b = async function () {
  try{
    var val = await a()
    console.log(val)
  }catch(err){
   console.error(err)
  }
}

b();

//out:100 or this is error
//tips
//try catch 捕获 await promise 必须用一个 async 函数包含await执行函数才能捕获异常错误
bingoogolapple commented 7 years ago

image 后面空了我也把这个加上去 👍

jackieli123723 commented 7 years ago

@bingoogolapple还可以优化哈适配移动端和美化哈滚动条:+1:

bingoogolapple commented 7 years ago

其实可以把你修改后的代码提交一下的,看能否在你这边借鉴一些东西,现在最新版把版权信息、备案信息、空视图加上了

jackieli123723 commented 7 years ago

@bingoogolapple 我的现在在仓库的blogDev分支,有空就弄哈,毕竟工作还是挺忙的,你的这个github授权id暴露了 给你解决方案看下面两个截图

tim 20170815172658 tim 20170815173125

bingoogolapple commented 7 years ago

👌 别人拿到这个也需要其他用户登录授权后才能进行操作,不过生产环境确实该设置成 false