在棘手的情况下,从javascript回调中返回一个值感到困惑

时间:2012-08-06 19:43:46

标签: javascript jquery node.js asynchronous

我正在制作一个小型的Node.js应用程序供个人使用,侧载上传到我的Twitter帐户(pic.twitter.com链接)的图片,使用他们的匿名API进行imgur,用新的替换pic.twitter.com链接-obtained imgur链接并将它们保存到磁盘。以下是执行此操作的代码:

var 
    jsdom   = require( 'jsdom' )
,   request = require( 'request' )
,   t_pic   = /http:\/\/pic.twitter.com\/([a-z0-9]+)/gi;

function rehostImage( match ) {
    request( match, function( e, r, b ) {
        if ( e ) throw e;
        jsdom.env(
            {
                html: b,
                scripts: ['http://code.jquery.com/jquery-1.7.2.min.js']
            }, 
            function( err, window ) {
                var $ = window.jQuery;
                request.post( 
                    'http://api.imgur.com/2/upload.json', 
                    { 
                        key: 'gh10z9DFZ009876E342dfsfd34234dszSD65XRV5',
                        image:$( '.twimg' ).find( 'img' ).attr( 'src' ) 
                    }, 
                    function( data ) { 
                        return data.upload.links.original; 
                    });
            });
    });
}

var tweets = [], i = 0;

/* code to GET twitter page using "request" goes here similar to rehostImage */

/* same jsdom boilerplate as in rehostImage function goes here to get 
   the jQuery handle on the page DOM. Once we get "$"... */

$( '.tweet-text' ).each( function() { 
    i++;
    tweets[ i ] = $( this ).html();
    if( tweets[i].match( t_pic ) ) { tweets[i].replace( t_pic, rehostImage ); }
});

代码尝试做的很简单:

  1. 获取我的推特页面
  2. 解析任何pic.twitter.com链接的每条推文
  3. 获取该页面,遍历DOM,找到图像URL并通过他们的匿名API上传到imgur
  4. 问题是正则表达式替换tweets[i].replace( t_pic, rehostImage )replace将函数作为第二个参数,其返回值用于替换匹配的字符串;在这种情况下,上传后的最终imgur URL data.upload.links.original将替换我的推文中的pic.twitter.com网址,然后我将其保存到本地磁盘。

    当通过回调在异步中发生所有问题时,如何让rehostImage返回data.upload.links.original回到正则表达式替换?通常的方法是采用最终操作,正则表达式替换,并将其作为回调传递,可以在data.upload.links.original之后运行,但由于正则表达式替换发生在内,我不知道如何在这里应用该方法。 / p>

    任何指针?

1 个答案:

答案 0 :(得分:1)

如果要在异步调用返回之前推迟执行替换,可以使用$.deferred实现此操作。

这是一个如何使用它的示例,您可能需要调整它以适合您的特定行为。

首先,您需要一个延迟对象:

var deferred = $.Deferred();

然后你的异步函数需要返回一个promise:

function rehostImage( match ) {
    // snip
    return deferred.promise();
}

你的替换回调将等待延迟解决:

tweets[i].replace(t_pic, function () {
    rehostImage().then(function (data) {
        // the callback you want to execute when the deferred resolves
    });
});

最后你的异步函数需要解决延迟:

function( data ) {
    deferred.resolve(data.upload.links.original); 
});