JavaScript 设计模式——处理不需要的异步

Posted

技术标签:

【中文标题】JavaScript 设计模式——处理不需要的异步【英文标题】:JavaScript Design Patterns -- Dealing With Unwanted Asynchrony 【发布时间】:2011-04-24 13:28:10 【问题描述】:

我对基于事件的编程非常陌生(使用 node.js)。我相信有些事情我只是不明白,因为有一个特殊的问题我一次又一次地遇到。

简而言之,当异步性似乎妨碍您时,该问题正在处理。在我的例子中,这最常体现在使用第三方库时,这些库在设计上是非阻塞的,并促进了基于回调的 API。

例如:现在我正在写一些大量使用mranney's node-redis library 的东西。我的程序正在抓取 RSS 提要并将结果放入 redis。我正在使用我认为是 redis 的常见策略:

    抓取提要,将结果存储为 redis 哈希,其键类似于 feed:<feedId>:results:<timestamp>。 在feed:<feedId>:latest 下存储对最新结果的引用。
var redis = require("redis"); var client = redis.createClient(); var get_latest_results = 函数 (feedId) client.get('feed:+ feedId + ':latest', function (err, res) var latest_reading_key = res.toString(); client.hgetall(latest_reading_key, function (err, res) var latest_reading = res; ); ); // 如何为这个函数指定返回值?

return latest_reading 放在get_latest_results 函数的底部失败,因为latest_reading 直到函数准备退出之后 才被定义。在hgetall 调用中放置return latest_reading 失败,因为return 引用回调,并被get_latest_results 忽略。

这只是我似乎经常要写的那种情况的一个例子。也许我正试图将方钉敲入圆孔,因为我不知道更好。似乎应该有一种非骇客的方法来解决这类问题。

【问题讨论】:

【参考方案1】:

您正在与异步作斗争,因为您仍在以同步范式编写函数。

在异步中,您应该将回调附加到事件。您不应该期望像get_latest_results() 这样的异步函数会得到结果,但是您应该将回调函数作为参数传递给它,以便在结果准备好时调用它。回调将对您的结果做任何需要做的事情:

var get_latest_results = function (feedId, readyCallback) 
    client.get('feed:' + feedId + ':latest', function (err, res) 
        var latest_reading_key = res.toString();
        client.hgetall(latest_reading_key, function (err, res) 
            readyCallback(res);                           //--- Trigger Callback
        );
    );
    // how do I specify a return value for this function? //--- You don't

然后你可以这样调用你的函数:

get_latest_results(1000, function (result) 
   //--- Do whatever needs to be done with the latest result...
);

【讨论】:

+1。学会喜欢它。 '因为 javascript 没有为您提供语言级别的原语,如线程或协程,您需要能够同步运行异步代码(反之亦然)。

以上是关于JavaScript 设计模式——处理不需要的异步的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript的异步处理

在JavaScript中同步与异步

架构设计|异步请求如何同步处理?

玩转javascript异步编程

玩转javascript异步编程

[书籍精读]《JavaScript异步编程》精读笔记分享