Promise、Generator与异步编程

10人阅读 评论(0) 收藏 举报
分类:

一、异步任务运行

执行异步操作的传统方式是调用一个包含回调的函数,例如:

let fs = require("fs");
fs.readFile("config.json", function(err, contents) {
if (err) {
throw err;
}
doSomethingWith(contents);
console.log("Done");
});

   当你拥有数量少而有限的任务需要完成时,这么做很有效;然而当你需要嵌套回调函数,或者要按顺序处理一系列的异步任务时,此方式就会非常麻烦了。在这种场合下,生成器与 yield 会很有用。

二、生成器实现异步编程

  由于 yield 能停止运行,并在重新开始运行前等待 next() 方法被调用,你就可以在没有回调函数的情况下实现异步调用。

let fs = require("fs");
function run(taskDef) {
    // 创建迭代器,让它在别处可用
    let task = taskDef();
    // 开始任务
    let result = task.next();
    // 递归使用函数来保持对 next() 的调用
    function step() {
        // 如果还有更多要做的
        if (!result.done) {
            if (typeof result.value === "function") {
                result.value(function(err, data) {
                        if (err) {
                        result = task.throw(err);
                        return;
                       }
                        result = task.next(data);
                        step();
                });
            } else {
                    result = task.next(result.value);
                    step();
            }
        }
    }
    // 开始处理过程
    step();
 }
// 定义一个函数来配合任务运行器使用
function readFile(filename) {
    return function(callback) {
            fs.readFile(filename, callback);
    };
}
// 运行一个任务
run(function*() {
    let contents = yield readFile("config.json");
    doSomethingWith(contents);
    console.log("Done");
});

  此例执行了异步的 readFile() 操作,而在主要代码中并未暴露出任何回调函数。除了yield 之外,此代码看起来与同步代码并无二致。既然执行异步操作的函数都遵循了同一接口,你就可以用貌似同步的代码来书写处理逻辑。当然,这些范例中所使用的模式也有缺点:你无法完全确认一个能返回函数的函数是异步的。

三、Promise与Generator结合实现异步编程

  借助 Promise ,你可以确保每个异步操作都返回一个 Promise ,从而大幅度简化并一般化异步处理,通用接口也意味着你可以大大减少异步代码。

let fs = require("fs");
function run(taskDef) {
    // 创建迭代器
    let task = taskDef();
    // 启动任务
    let result = task.next();
    // 递归使用函数来进行迭代
    (function step() {
        // 如果还有更多要做的
        if (!result.done) {
            // 决议一个 Promise ,让任务处理变简单
            let promise = Promise.resolve(result.value);
            promise.then(function(value) {
                result = task.next(value);
                step();
            }).catch(function(error) {
                result = task.throw(error);
                step();
            });
        }
    }());
}
// 定义一个函数来配合任务运行器使用
function readFile(filename) {
    return new Promise(function(resolve, reject) {
        fs.readFile(filename, function(err, contents) {
            if (err) {
                reject(err);
            } else {
                resolve(contents);
            }
        });
    });
}
// 运行一个任务
run(function*() {
    let contents = yield readFile("config.json");//readFile执行异步操作
    doSomethingWith(contents);
    console.log("Done");
});

  调用 Promise.resolve() 只为预防未正确返回Promise 的函数(记住: Promise.resolve() 在被传入任意 Promise 时只会直接将其传递回来,而不是 Promise 的参数则会被包装为 Promise )。

  run() 函数能运行任意使用 yield 来实现异步代码的生成器,而不会将 Promise (或回调函数)暴露给开发者。事实上,由于函数调用后的返回值总是会被转换为一个 Promise ,该函数甚至允许返回 Promise 之外的类型。这意味着同步与异步方法在使用 yield 时都会正常工作,并且你永不需要检查返回值是否为一个 Promise 。唯一需要担心的是,要确保诸如 readFile() 的异步方法能返回一个正确标记其状态的Promise 。

  若只是单纯的使用Promise实现异步编程,只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。并且原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。所以将Promise和Generator结合使用,效果最佳。



查看评论

异步编程——promise

异步编程——promise定义 Promise是异步编程的一个解决方案,相比传统的解决方法——回调函数,使用Promise更为合理和强大,避免了回调函数之间的层层嵌套,也使得代码结构更为清晰,便于...
  • eidolons
  • eidolons
  • 2017-04-29 14:33:23
  • 442

异步编程Promise的简单实现

promise模式-那么多中异步编程的方式,为什么选择promise, 因为前面几种方式不够灵活,用起来不够痛快,不优雅。为了降低异步编程的复杂性,所以promise。promise的核心是有一个pr...
  • jl244981288
  • jl244981288
  • 2015-07-31 10:14:42
  • 1215

异步解决方案Promise

回调地狱callback hell最大的问题不是因为缩进。它引起的问题比缩进要大得多。根本它真正的问题是剥夺了程序员使用return和throw等捕捉错误和返回值的能力。 程序的执行流程是基于一个...
  • jlin991
  • jlin991
  • 2017-03-02 22:34:16
  • 136

ES6--Promise、Generator及async

ES6诞生以前,异步编程的方法,大概有如下四种:回调函数、事件监听、发布/订阅、Promise对象;ES6中,引入了Generator函数;ES7中,async更是将异步编程带入了一个全新的阶段。十四...
  • ligang2585116
  • ligang2585116
  • 2017-04-27 10:28:15
  • 3760

Promise和Generator

代码案例以及文章内容均来自阮一峰的ECAMScript6入门:http://es6.ruanyifeng.com/#docs/promisePromise对象Promise 是异步编程的一个解决方案,...
  • qq_22329521
  • qq_22329521
  • 2017-03-29 15:31:28
  • 706

Promise异步编程模式总结

Promise是JavaScript中的一种异步编程范式, 一个Promise对象表示一个即将完成但还未完成的操作。 鉴于JavaScript中异步和回调的编程风格, Promise模式可以有...
  • clschen
  • clschen
  • 2016-08-19 14:30:32
  • 854

用 ES6 generator & Promise 写异步代码

测试文件[root@nginx ~]# cat test_1.txt this is test_1.txt [root@nginx ~]# cat test_2.txt this is test_2...
  • dongsoso
  • dongsoso
  • 2015-08-14 18:55:12
  • 1735

ECMAScript 6 入门笔记(五)异步promise,Generator,async

前面弄完了ECMAScript6的基础对象扩展,下来来看下异步编程的三个方法PromisePromise.prototype.then() Promise.prototype.catch() Pr...
  • qq_20334295
  • qq_20334295
  • 2017-04-01 18:53:44
  • 1214

Promise模式简介(Future) --- Java实现异步

Promise模式简介 Promise模式是一种异步编程模式 。它使得我们可以先开始一个任务的执行,并得到一个用于获取该任务执行结果的凭据对象,而不必等待该任务执行完毕就可以继续执行其他操作。等...
  • u011499747
  • u011499747
  • 2016-02-23 18:00:42
  • 7551

异步javascript,callback、Promise?我们用Generator!

ES6提供了两个处理异步Js的特性:Promise和Generator。我们这里会介绍这两个新特性,并在最后讲解如何使用Generator。为了使本文更加贴近实际,我们使用一个网络请求库request...
  • future_challenger
  • future_challenger
  • 2016-08-16 22:13:58
  • 1401
    个人资料
    等级:
    访问量: 22
    积分: 40
    排名: 184万+
    文章分类
    文章存档