[关闭]
@demonly 2017-10-14T04:05:54.000000Z 字数 2656 阅读 869

异步编程

JavaScript


Node 的异步机制

事件循环

进程启动时,Node 就会创建一个循环,每执行一次循环体的过程称为 Tick。

Created with Raphaël 2.1.2开始询问观察者是否有事件?取出一个事件是否关联有回调函数执行回调函数退出yesnoyes

线程池

观察者的回调函数来自于线程池。每次 Tick 的执行过程中,它都会检查线程池中是否有执行完的请求,如果存在,就会将请求对象加入到观察者的队列中。

在调用的时候请求对象的 result 属性作为参数,oncomplete_sym 属性作为方法。

异步调用

当发起异步调用的时候,底层首先创建一个请求对象,然后将 JavaScript 层中传入的参数和方法封装在请求对象的 result 属性和 oncompelet_sym 属性中。然后将这个对象推入到线程池中等待执行。

非 I/O 的异步 API

另外:process.nextTick 属于 idle 观察者,setImmediate 属于 cheek 观察者,idle 观察者先于 cheek 观察者。

事件发布/订阅模式

可以通过继承 events 模块来利用事件机制解决业务问题。
API

  1. // 订阅
  2. emitter.on('event1', function(e) {
  3. console.log(e);
  4. });
  5. // 发布
  6. emitter.emit('event1', 'I am message');

实现

  1. var events = require('events');
  2. var util = require('util');
  3. function Emitter() {
  4. events.EventEmitter.call(this);
  5. }
  6. util.inherits(Emitter, events.EventEmitter);
  7. var emitter = new Emitter();

Promise/Deferred 模式

API
then(fulfilledHandler, errorHandler, progressHandler)

  1. var readFile = smooth(fs.readFile);
  2. readFile('file1.txt', 'utf-8').then(function (file1) {
  3. return readFile(file1.trim(), 'utf-8');
  4. }).then(function (file2) {
  5. console.log(file2);
  6. });

实现

  1. // Promise
  2. var Promise = function() {
  3. this.queue = [];
  4. this.isPromise = true;
  5. };
  6. Promise.prototype.then = function (fulfilledHandler, errorHandler, progressHandler) {
  7. var handler = {};
  8. // 将事件处理程序绑定在 handler 对象上
  9. if (typeof fulfilledHandler === 'function') {
  10. handler.fulfilled = fuldilledHandler;
  11. }
  12. if (typeof errorHandler === 'function') {
  13. handler.error = errorHandler;
  14. }
  15. // 将 handler 对象推入队列
  16. this.queue.push(handler);
  17. return this;
  18. };
  19. // Deferred
  20. var Deferred = function () {
  21. this.promise = new Promise();
  22. };
  23. // 完成态
  24. Deferred.prototype.resolve = function (obj) {
  25. var promise = this.promise;
  26. var handler;
  27. // 将队列中的 handler 对象逐个取出
  28. while ((handler = promise.queue.shift())) {
  29. // 判断是否有相应状态的处理函数
  30. if (handler && handler.fulfilled) {
  31. // 调用处理函数并保存结果
  32. var ret = handler.fulfilled(obj);
  33. // 用返回的 promise 对象替代原本的,因为每 Promise 化一个函数都会新建一个 Deferred
  34. if (ret && ret.isPromise) {
  35. ret.queue = promise.queue;
  36. this.promise = ret;
  37. return;
  38. }
  39. }
  40. }
  41. };
  42. // 失败态
  43. Deferred.prototype.reject = function (obj) {
  44. var promise = this.promise;
  45. var handler;
  46. while ((handler = promise.queue.shift())) {
  47. if (handler && handler.error) {
  48. var ret = handler.error(obj);
  49. if (ret && ret.isPromise) {
  50. ret.queue = promise.queue;
  51. this.promise = ret;
  52. return;
  53. }
  54. }
  55. }
  56. };
  57. // 生成回调函数,在异步方法中传入这个函数
  58. Deferred.prototype.callback = function () {
  59. //将 this 传入回调函数
  60. var that = this;
  61. return function (err, file) {
  62. if (err) {
  63. return that.reject(err);
  64. }
  65. that.resolve(file);
  66. };
  67. };
  68. // 将方法 Promise 化
  69. var smooth = function(method) {
  70. return function () {
  71. var deferred = new Deferred();
  72. var args = Array.prototype.slice.call(arguments, 0);
  73. args.push(deferred.callback());
  74. method.apply(null, args);
  75. return deferred.promise;
  76. };
  77. };
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注