异步

异步的特点:不等待 非阻塞,同时处理大量的并发请求,使得性能提高

JavaScript为单线程运行,如果程序为同步执行的,在发送http请求,读写文件等操作中,线程阻塞,程序将无法响应其他操作。所以实现异步后,性能有很大提升。且由于是单线程运行,没有线程同步等的问题。

阻塞代码

// 阻塞式的
const fs = require("fs");
const data = fs.readFileSync("./hello.js");	
console.log(data.toString());
console.log("123");

// 先输出文件内容,再输出123

JavaScript异步编程的几种常见模式

  • 回调函数 callback
  • Promise
  • Generator
  • async / await
  • Event

回调函数

回调函数在异步操作完成后被调用

// 非阻塞
const fs = require("fs");
fs.readFile("./hello.js", function (err, data) {	// 回调函数
  // 错误优先机制
  if (err) {
    console.log(err.stack);
    return;
  }
  // 未指定编码格式,得到的data为buffer对象,使用toString方法
  console.log(data.toString());
});
console.log("123");

// 先输出123,再输出文件内容

Promise

用法

const myReadFile = (filename) => {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, "utf8", (err, data) => {
      if (err) {
        reject(err);
      }
      resolve(data);
    });
  });
};
myReadFile('./hello.js')
.then(res => {
  console.log(res);
}, (error) => {
  console.error("error: " + error);
});

使用Promise解决回调地狱

func1()
.then(res1 => {
  // do something
  return func2();
})
.then(res2 => {
  // do something
  return func3();
})
.catch(error => {
  // handle error
})

使用模块

const fs = require("fs");
const { promisify } = require("util");
// promisify 将 fs.readFile包装成promise对象
const readFile = promisify(fs.readFile);

async function asyncReadFile() {
  try {
    const data = await readFile("./hello.js");
    console.log(data.toString());
  } catch (error) {
    console.log(error.stack);
  }
}

asyncReadFile();

generator

const fs = require("fs");
const { promisify } = require("util");
// // promisify 将 fs.readFile包装成promise对象
const readFile = promisify(fs.readFile);
function* read() {
  yield readFile("./hello.js");
}

let ge = read();
ge.next().value.then((data) => {
  console.log(data.toString());
});

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

http与https 上一篇
实现Promise.all方法 下一篇