JavaScript 设计模式——处理不需要的异步 [英] JavaScript Design Patterns -- Dealing With Unwanted Asynchrony

查看:35
本文介绍了JavaScript 设计模式——处理不需要的异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

  1. 刮取提要,将结果存储为 redis 哈希,其键类似于 feed:<feedId>:results:<timestamp>.
  2. feed::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, 函数 (err, res) {var latest_reading = res;});});//我如何为这个函数指定一个返回值?}

get_latest_results 函数底部放置return latest_reading 失败,因为latest_reading 直到after 函数准备退出时才定义.将 return latest_reading 放在 hgetall 调用中失败,因为 return 指的是回调,并且被 get_latest_results 忽略.

这只是我似乎经常写的那种情况的一个例子.也许我想把方钉敲进圆孔,因为我不知道更好.似乎确实应该有一种非黑客的方法来解决这类问题.

解决方案

您正在为异步而苦苦挣扎,因为您仍在以同步范式编写函数.

在异步中,您应该将回调附加到事件.您不应该期望像 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, 函数 (err, res) {readyCallback(res);//--- 触发回调});});//我如何为这个函数指定一个返回值?//--- 你没有}

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

get_latest_results(1000, function (result) {//--- 用最新的结果做任何需要做的事情...});

I'm pretty new to event-based programming (using node.js). I believe that there's something I'm just not grokking about it, because there's a particular problem that I keep coming across again and again and again.

In short, that problem is dealing with asynchronicity when it seems to be getting in your way. This most often manifests itself, in my case, when working with third-party libraries, which are non-blocking by design and promote a callback-based API.

For instance: Right now I'm writing some stuff that makes heavy use of mranney's node-redis library. My program is scraping RSS feeds and tucking the results into redis. I'm using what I believe is a common strategy with redis:

  1. Scrape feed, store results as a redis hash with a key of something like feed:<feedId>:results:<timestamp>.
  2. Store reference to the latest result under feed:<feedId>:latest.

var redis = require("redis");
var client = redis.createClient();

var get_latest_results = function (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;
        });
    });
    // how do I specify a return value for this function?
}

Placing return latest_reading at the bottom of the get_latest_results function fails, because latest_reading isn't defined until after the function is ready to exit. Placing return latest_reading within the hgetall call fails because the return refers to the callback, and is ignored by get_latest_results.

This is just one example of the kind of situation I seem constantly to write my way into. Maybe I'm trying to pound the square peg into the round hole because I don't know any better. It does seem that there should be a non-hackish way of solving this class of problems.

解决方案

You are struggling with asynchrony because you are still writing your functions in a synchronous paradigm.

In asynchrony you should attach callbacks to events. You shouldn't expect a result from an asynchronous function like get_latest_results(), but you should pass it a callback function as an argument to be invoked when the results are ready. The callback will do whatever needs to be done with your 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
}

Then you can call your function like this:

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

这篇关于JavaScript 设计模式——处理不需要的异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆