Nodejs也谈用ES6的generator和yield缓解回调陷阱:用过wait.for-ES6么?有更好的推荐么?

Nodejs也谈用ES6的generator和yield缓解回调陷阱:用过wait.for-ES6么?有更好的推荐么?

最近研究用 node --harmony 语法中新增的语法 generatoryield 缓解 回调陷阱, 于是找到了这个 wait.for-ES6, 以异步函数dns.resove为例, 它带来的顺序化方案是类似这样的:

var dns = require("dns"), 
      wait=require('wait.for-es6');

function* test(){
    var addresses = yield wait.for(dns.resolve4, "google.com");
    for (var i = 0; i < addresses.length; i++) {
        var a = addresses[i];
        console.log("reverse for " + a + ": " + JSON.stringify( yield wait.for(dns.reverse,a)));
    }
}

wait.launchFiber(test); 

其中 yield wait.for(dns.resolv4, "google.com"); 也可以把wait.for省略掉简写成:

var addresses = yield [dns.resolv4, "google.com"];//魔幻的简化

适用于解决现有项目中的大部分回调陷阱,用着还挺顺手的, 不知道诸位有没有更好的模块推荐?


6 回复

Node.js 也谈用 ES6 的 generator 和 yield 缓解回调陷阱:用过 wait.for-ES6 吗?有更好的推荐吗?

最近我在研究如何使用 node --harmony 语法中新增的 generatoryield 来缓解回调地狱(callback hell)。通过这种方式可以更优雅地处理异步操作。我找到了一个名为 wait.for-ES6 的库,它可以帮助我们更方便地使用这种模式。

示例代码

假设我们要使用 dns.resolve4 方法来解析 Google 的 IPv4 地址,并且需要对每个地址进行反向解析。下面是具体的实现:

const dns = require("dns");
const wait = require('wait.for-es6');

// 定义一个生成器函数
function* test() {
    // 使用 yield 等待异步操作完成
    const addresses = yield wait.for(dns.resolve4, "google.com");

    // 遍历所有解析到的 IP 地址
    for (let i = 0; i < addresses.length; i++) {
        const a = addresses[i];
        // 对每个 IP 地址进行反向解析
        console.log(`reverse for ${a}: ${JSON.stringify(yield wait.for(dns.reverse, a))}`);
    }
}

// 启动生成器函数
wait.launchFiber(test);

在这个例子中,我们定义了一个生成器函数 test,并在其中使用了 yield 关键字来等待异步操作完成。具体来说,我们首先解析 Google 的 IPv4 地址,然后对每个解析到的地址进行反向解析。

更简洁的写法

wait.for-ES6 还提供了一种更简洁的写法,可以直接将待执行的异步函数和参数传递给 yield

const dns = require("dns");
const wait = require('wait.for-es6');

function* test() {
    // 直接使用数组简化 yield 表达式
    const addresses = yield [dns.resolve4, "google.com"];
    
    for (let i = 0; i < addresses.length; i++) {
        const a = addresses[i];
        console.log(`reverse for ${a}: ${JSON.stringify(yield [dns.reverse, a])}`);
    }
}

其他推荐

虽然 wait.for-ES6 是一种很好的解决方案,但如果你在寻找其他替代方案,可以考虑以下几种:

  1. async/await: 这是现代 Node.js 中最常用的异步处理方式,它基于 Promise,并且语法更加简洁易懂。

    const dns = require("dns");
    
    async function test() {
        const addresses = await dns.promises.resolve4("google.com");
        for (const a of addresses) {
            const reverse = await dns.promises.reverse(a);
            console.log(`reverse for ${a}: ${JSON.stringify(reverse)}`);
        }
    }
    
    test();
    
  2. co: 另一个流行的库,用于处理生成器函数中的异步操作。

    const co = require('co');
    const dns = require("dns");
    
    function* test() {
        const addresses = yield dns.promises.resolve4("google.com");
        for (const a of addresses) {
            const reverse = yield dns.promises.reverse(a);
            console.log(`reverse for ${a}: ${JSON.stringify(reverse)}`);
        }
    }
    
    co(test);
    

以上就是关于使用 generatoryield 缓解回调陷阱的一些探讨和示例代码,希望对你有所帮助!


好东西, 一会研究下, 现在最火使用最多的当然是 TJ 大神的 co 模块了, 强烈建议看一下, 在 co 的基础之上 TJ 给出了新的web开发框架 koa. 最近大家都在看哈

Thanks, 我也关注co了, 跟wait.for异曲同工之妙

很好的新特性, 可是好遥远啊!

使用 ES6 的 generator 和 yield 可以有效缓解 Node.js 中的回调地狱问题。wait.for-ES6 是一个可以实现这一目标的库,但还有其他一些工具和方法可以实现相同的效果。

示例代码

const dns = require('dns');
const wait = require('wait.for-es6');

function* test() {
    try {
        const addresses = yield wait.for(dns.resolve4, 'google.com');
        for (let i = 0; i < addresses.length; i++) {
            const a = addresses[i];
            console.log(`reverse for ${a}: ${JSON.stringify(yield wait.for(dns.reverse, a))}`);
        }
    } catch (err) {
        console.error(err);
    }
}

wait.launchFiber(test);

解释

  1. Generator 函数test 是一个 generator 函数,使用 function* 语法定义。
  2. 等待异步操作yield wait.for(...) 用于等待异步操作完成,并获取结果。
  3. 错误处理:使用 try...catch 块来捕获可能发生的错误。

其他推荐

除了 wait.for-ES6,你还可以考虑以下库:

  1. async/await: 这是 ES2017 引入的新特性,可以更直观地编写异步代码。

    const dns = require('dns');
    
    async function test() {
        try {
            const addresses = await dns.promises.resolve4('google.com');
            for (const address of addresses) {
                const reversed = await dns.promises.reverse(address);
                console.log(`reverse for ${address}: ${JSON.stringify(reversed)}`);
            }
        } catch (err) {
            console.error(err);
        }
    }
    
    test();
    
  2. co: 这是一个由 TJ 大神编写的库,用于简化 generator 函数的使用。

    const co = require('co');
    const dns = require('dns');
    
    co(function* () {
        try {
            const addresses = yield dns.promises.resolve4('google.com');
            for (const address of addresses) {
                const reversed = yield dns.promises.reverse(address);
                console.log(`reverse for ${address}: ${JSON.stringify(reversed)}`);
            }
        } catch (err) {
            console.error(err);
        }
    });
    

这些方法都可以帮助你更好地管理异步代码,选择哪种方式取决于你的具体需求和个人偏好。

回到顶部