首页 web前端 js教程 node.js下when.js 的异步编程实践_node.js

node.js下when.js 的异步编程实践_node.js

May 16, 2016 pm 04:29 PM
node.js 异步编程

假设一个业务场景:

通过rss地址,获取rss并保存于文件,rss地址保存于文件中。

完成该场景的业务需要完成3个任务:

1.从文件中读取rss地址。

2.获取rss。

3.保存于文件。

最后将这三个任务进行整合。

准备:

存放rss地址的文件,address.txt。

http://programmer.csdn.net/rss_programmer.html
 
任务1:

读取rss地址文件的内容并通过callback返回。

复制代码 代码如下:

var getRssAddress = function(path, callback) {
  fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
    callback(err, data);
  });
}

任务2:

 通过rss地址get到rss,并通过callback返回错误或数据。

复制代码 代码如下:

var getRss = function(url, callback) {
  var data = '';
  http.get(url, function(res) {
    res.on('data', function(chrunk) {
      data += chrunk;
    });
    res.on('end', function() {
      callback(null, data);
    });
  }).on('error', function(err) {
    callback(err, null);
  });
}

 

任务3:

将rss保存于文件并通过callback返回错误。

复制代码 代码如下:

var saveRss = function(data, callback) {
  fs.writeFile('rss.txt', data, 'utf8', function(err) {
    callback(err);
  });
}

整合:

复制代码 代码如下:

getRssAddress('address.txt', function(err, data) {
  if(err) {
    console.log(err);
    return;
  }
  getRss(data, function(err, data) {
    if(err) {
      console.log(err);
      return;
    }
    saveRss(data, function(err) {
      if(err) console.log(err);
    });
  });
});

上面的代码是全异步处理,使用最常见的callback处理异步逻辑的返回,好处是标准写法,大家都能容易接受;坏处是耦合性太强,处理异常麻烦,代码不直观,特别是处理业务逻辑复杂和处理任务多的场景,层层的callback会让人眼冒金星,代码难以维护。

Promise/A规范的实现之一when.js正是针对这样的问题域。

让我们来看一下改造后的代码。

任务1:

复制代码 代码如下:

var getRssAddress = function(path) {
    var deferred = when.defer();
      fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
        if (err) deferred.reject(err);
        deferred.resolve(data);
      });

    return deferred.promise;
}


 
任务2:

复制代码 代码如下:

var getRss = function(url) {
  var deferred = when.defer();
    var data = '';
    http.get(url, function(res) {
      res.on('data', function(chrunk) {
        data += chrunk;
      });
      res.on('end', function() {
        deferred.resolve(data);
      });
    }).on('error', function(err) {
      deferred.reject(err);
    });

    return deferred.promise;
}

任务3:

复制代码 代码如下:

var saveRss = function(data) {
  var deferred = when.defer();
  fs.writeFile('rss.txt', data, 'utf8', function(err) {
    if(err) deferred.reject(err);
    deferred.resolve();
  });

  return deferred.promise;
}


 

整合:

复制代码 代码如下:

getRssAddress('address.txt')
  .then(getRss)
  .then(saveRss)
  .catch(function(err) {
    console.log(err);
  });

解释:

promise/A规范定义的“Deferred/Promise”模型就是“发布/订阅者”模型,通过Deferred对象发布事件,可以是完成resolve事件,或者是失败reject事件;通过Promise对象进行对应完成或失败的订阅。

在Promises/A规范中,每个任务都有三种状态:默认(pending)、完成(fulfilled)、失败(rejected)。

1.默认状态可以单向转移到完成状态,这个过程叫resolve,对应的方法是deferred.resolve(promiseOrValue);

2.默认状态还可以单向转移到失败状态,这个过程叫reject,对应的方法是deferred.reject(reason);

3.默认状态时,还可以通过deferred.notify(update)来宣告任务执行信息,如执行进度;

4.状态的转移是一次性的,一旦任务由初始的pending转为其他状态,就会进入到下一个任务的执行过程中。

按照上面的代码。

通过when.defer定义一个deferred对象。

var deferred = when.defer();
异步数据获取成功后,发布一个完成事件。

deferred.resolve(data);
异步数据获取失败后,发布一个失败事件。

deferred.reject(err);
并且返回Promise对象作为订阅使用。

return deferred.promise;
订阅是通过Promise对象的then方法进行完成/失败/通知的订阅。

getRssAddress('address.txt')
  .then(getRss)
then有三个参数,分别是onFulfilled、onRejected、onProgress

promise.then(onFulfilled, onRejected, onProgress)
上一个任务被resolve(data),onFulfilled函数就会被触发,data作为它的参数.

上一个任务被reject(reason),那么onRejected就会被触发,收到reason。

任何时候,onFulfilled和onRejected都只有其一可以被触发,并且只触发一次。

对于处理异常,when.js也提供了极其方便的方法,then能传递错误,多个任务串行执行时,我们可以只在最后一个then定义onRejected。也可以在最后一个then的后面调用catch函数捕获任何一个任务的异常。

如此写法简单明了。

复制代码 代码如下:

getRssAddress('address.txt')
  .then(getRss)
  .then(saveRss)
  .catch(function(err) {
    console.log(err);
  });

Promise给异步编程带来了巨大的方便,可以让我们专注于单个任务的实现而不会陷入金字塔厄运,以上代码仅仅是基本使用,when.js提供的功能远远不止本文提到的这些,具体参照官方API。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何用 C++ 函数实现异步编程? 如何用 C++ 函数实现异步编程? Apr 27, 2024 pm 09:09 PM

摘要:C++中的异步编程允许多任务处理,无需等待耗时操作。使用函数指针创建指向函数的指针。回调函数在异步操作完成时被调用。boost::asio等库提供异步编程支持。实战案例演示了如何使用函数指针和boost::asio实现异步网络请求。

PHP中如何使用ReactPHP进行异步编程 PHP中如何使用ReactPHP进行异步编程 Jun 27, 2023 am 09:14 AM

随着Web应用程序变得越来越复杂,程序员不得不采用异步编程来处理大量请求和I/O操作。PHP:HypertextPreprocessor也不例外。为了满足这一需求,ReactPHP已经成为目前最受欢迎的PHP异步编程框架之一。在本文中,将讨论如何在PHP中使用ReactPHP进行异步编程。1.ReactPHP简介ReactPHP是一个基于事件驱动编程

JavaScript函数异步编程:处理复杂任务的必备技巧 JavaScript函数异步编程:处理复杂任务的必备技巧 Nov 18, 2023 am 10:06 AM

JavaScript函数异步编程:处理复杂任务的必备技巧引言:在现代前端开发中,处理复杂任务已经成为了必不可少的一部分。而JavaScript函数异步编程技巧则是解决这些复杂任务的关键。本文将介绍JavaScript函数异步编程的基本概念和常用的实践方法,并提供具体的代码示例,帮助读者更好地理解和使用这些技巧。一、异步编程的基本概念在传统的同步编程中,代码按

如何在PHP中实现异步消息处理 如何在PHP中实现异步消息处理 Jul 10, 2023 am 08:19 AM

如何在PHP中实现异步消息处理引言:在现代的Web应用程序中,异步消息处理变得越来越重要。异步消息处理可以提高系统的性能和可扩展性,并改善用户体验。PHP作为一种常用的服务器端编程语言,也可以通过一些技术来实现异步消息处理。在本文中,我们将介绍一些PHP中实现异步消息处理的方法,并提供代码示例。使用消息队列消息队列是一种解耦系统组件的方式,它允许不同的组件在

深入理解PHP8的新特性:如何高效使用异步编程和代码? 深入理解PHP8的新特性:如何高效使用异步编程和代码? Sep 11, 2023 pm 01:52 PM

深入理解PHP8的新特性:如何高效使用异步编程和代码?PHP8是PHP编程语言的最新主要版本,带来了许多令人兴奋的新特性和改进。其中最突出的特性之一是对异步编程的支持。异步编程允许我们在处理并发任务时提高性能和响应能力。本文将深入探讨PHP8的异步编程特性,并介绍如何高效地使用它们。首先,让我们了解一下什么是异步编程。在传统的同步编程模型中,代码按照线性的顺

Java框架异步编程中的常见问题与解决方案 Java框架异步编程中的常见问题与解决方案 Jun 04, 2024 pm 05:09 PM

Java框架异步编程中常见的3个问题和解决方案:回调地狱:使用Promise或CompletableFuture以更直观的风格管理回调。资源竞争:使用同步原语(如锁)保护共享资源,并考虑使用线程安全集合(如ConcurrentHashMap)。未处理异常:明确处理任务中的异常,并使用异常处理框架(如CompletableFuture.exceptionally())处理异常。

golang框架如何处理并发和异步编程? golang框架如何处理并发和异步编程? Jun 02, 2024 pm 07:49 PM

Go框架利用Go的并发和异步特性提供高效处理并发和异步任务的机制:1.通过Goroutine实现并发,允许同时执行多个任务;2.通过通道实现异步编程,在不阻塞主线程的情况下执行任务;3.适用于实战场景,如并发处理HTTP请求、异步获取数据库数据等。

Python异步编程: 实现高效并发的异步代码之道 Python异步编程: 实现高效并发的异步代码之道 Feb 26, 2024 am 10:00 AM

1.为什么要使用异步编程?传统编程使用阻塞式I/O,这意味着程序会等待某个操作完成,然后才能继续执行。这对于处理单个任务来说可能很有效,但对于处理大量任务时,可能会导致程序变慢。异步编程则打破了传统阻塞式I/O的限制,它使用非阻塞式I/O,这意味着程序可以将任务分发到不同的线程或事件循环中执行,而无需等待任务完成。这允许程序同时处理多个任务,提高程序的性能和效率。2.python异步编程的基础Python异步编程的基础是协程和事件循环。协程是允许函数在暂停和恢复之间切换的函数。事件循环则负责调度

See all articles