# 异步编程

计算机在设计上是异步,但实际上,计算机的每个程序都运行与特定的时间段,然后停止执行,以便让另一个程序继续执行,这件事发生的非常之快,以至于我们根本无法察觉,让我们假以为计算机可以同时运行续作程序(PS: 多核处理器除外)

通常来说,编程语言是同步的,有些语言会在语言或库中提供管理异步性的方法,其中一些语言通过使用线程来处理异步操作,而 Node.js 引入了非阻塞的 I/O 环境,并将改概念扩展到文件访问、网络调用等;

# 回调函数

自己定义函数让别人去调用。

function getData(callback) {
  callback("123");
}
getData(function (n) {
  console.log(n);
  console.log("callback函数被调用了");
}); //调用getData函数,传递参数是一个回调函数
// 123
// callback函数被调用了

# Promise

Promise 通常会被定义为 最终会变为可用值的代理

Promise 的状态 pending resolve reject

# 创建 Promise

let done = true;
const isItDoneYet = new Promise((resolve, reject) => {
  if (done) {
    const workDone = "这是创建的东西";
    resolve(workDone);
  } else {
    const why = "仍然在处理其他事情";
    reject(why);
  }
});
console.log(isItDoneYet);
// Promise { '这是创建的东西' }

# 使用 Promise

const checkItsDone = () => {
  isItDoneYet
    .then((ok) => {
      console.log(ok);
    })
    .catch((err) => {
      console.log(err);
    });
};

# 链式调用

Promise 可以返回另一个 Promise,从而创建一个 Promise 链
示例:

const status = (response) => {
  if ((response.status >= 200 && response.status < 300) || response.status == 304) {
    return Promise.resolve(response);
  } else {
    return Promise.reject(new Error(response.statusText));
  }
};
const json = (response) => response.json();

fetch("./test.json")
  .then(status)
  .then(json)
  .then((data) => {
    console.log(data);
  })
  .then((error) => {
    console.log(error);
  });

这里 response 有一个 json()方法,该方法会返回一个 promise,该 promise 解决时会传入已经处理成 JSON 的响应体的内容;
执行过程,先执行 fetch,成功后执行 status,status 成功执行 json,json 成功执行 console.log(data),但凡有一个失败,都会直接跳到底部的 catch
如果 catch()内部引发错误,则可以附加第二个 catch()来处理,以此类推;

new Promise((resolve, reject) => {
  throw new Error("错误1");
})
  .catch((err) => {
    throw new Error("错误2");
  })
  .catch((err) => {
    console.error(err);
  });
// Error: 错误2

# 编排 Promise

Promise.all([f1, f2]) 所有 Promise 都成功解决
Promise.race([first, second]) 其中一个 Promise 被解决或拒绝

# Generator

function* 这种声明方式会定义一个生成器函数,它返回一个 Generator(生成器)对象
生成器函数在执行时能够暂停,后面又能从暂停处继续执行。
调用一个生成器函数并不会马上执行里面的语句,返回一个这个生成器的迭代器(iterator)对象,当这个迭代器的 next()方法被调用时,其内的语句会执行到第一个 yield 的位置为止

example:

function* countAppleSales() {
  var x = 0;
  var saleList = [3, 7, 5];
  for (var i = 0; i < saleList.length; i++) {
    yield saleList[i];
  }
}
const appleStore = countAppleSales();
console.log(appleStore.next());
console.log(appleStore.next());
console.log(appleStore.next().value);
console.log(appleStore.next());
// { value: 3, done: false; }
// { value: 7, done: false; }
// 5;
// { value: undefined, done: true; }

# Async 和 Await

example:

const doSomethingAsync = () => {
  return new Promise((resolve) => {
    setTimeout(() => resolve("做些什么"), 3000);
  });
};
const doSomething = async () => {
  console.log(await doSomethingAsync());
};
console.log("之前");
doSomething();
console.log("之后");
// 之前
// 之后
// 做些什么