最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use of dummy and empty jQuery promises - Stack Overflow

programmeradmin0浏览0评论

I run multiple animations and perform some action when they're plete, using jQuery promises:

$.when(foo(),  
       bar(),  
       baz())  
 .done(allDone);  

Each function (foo, etc.) returns a jQuery.Promise().

Now say I want to include a function which doesn't animate anything, but its timing is related to the animations - I can't include it in the chain, as it doesn't return a promise.

So I can hack it like so:

function qux() {
  if (something) {
    return $(".whatever")
      .removeClass("bob")
      .addClass("fred")
      .append(/*...do stuff...*/)
      .animate({ left: "+=0" }, 0, callback ) // <-- dummy animation does nothing
      .promise();                             // <-- this is a dummy promise
  }
  else {
    return $().promise();                     // <-- this is an "empty" promise
  }
}

And now I can chain it:

$.when(foo(),  
       bar(),  
       baz(),
       qux())  
 .done(allDone);  

This works. But I'm bending the rules here - are there any gotchas I haven't taken into account, or am I somehow stomping on the fx queue?

UPDATE
As per answers below, the qux() function can be rewritten as:

function qux() {
  if (something) {
    $(".whatever")
      .removeClass("bob")
      .addClass("fred")
      .append(/*...do stuff...*/);
  }
}

I run multiple animations and perform some action when they're plete, using jQuery promises:

$.when(foo(),  
       bar(),  
       baz())  
 .done(allDone);  

Each function (foo, etc.) returns a jQuery.Promise().

Now say I want to include a function which doesn't animate anything, but its timing is related to the animations - I can't include it in the chain, as it doesn't return a promise.

So I can hack it like so:

function qux() {
  if (something) {
    return $(".whatever")
      .removeClass("bob")
      .addClass("fred")
      .append(/*...do stuff...*/)
      .animate({ left: "+=0" }, 0, callback ) // <-- dummy animation does nothing
      .promise();                             // <-- this is a dummy promise
  }
  else {
    return $().promise();                     // <-- this is an "empty" promise
  }
}

And now I can chain it:

$.when(foo(),  
       bar(),  
       baz(),
       qux())  
 .done(allDone);  

This works. But I'm bending the rules here - are there any gotchas I haven't taken into account, or am I somehow stomping on the fx queue?

UPDATE
As per answers below, the qux() function can be rewritten as:

function qux() {
  if (something) {
    $(".whatever")
      .removeClass("bob")
      .addClass("fred")
      .append(/*...do stuff...*/);
  }
}
Share Improve this question edited Jul 30, 2014 at 11:45 Bobby B asked Jul 30, 2014 at 8:53 Bobby BBobby B 2,3253 gold badges25 silver badges48 bronze badges 8
  • As per @YuryTarabanko answer, empty promise is unnecessary: "If a single argument is passed to jQuery.when and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.". I suppose it works for the multi-argument case too. – Bobby B Commented Jul 30, 2014 at 9:15
  • 1 Yes, it works for the multiple argument case, and also with real promises such as Bluebird or native promises using Promise.all. – Benjamin Gruenbaum Commented Jul 30, 2014 at 9:18
  • 1 I would still return an empty promise if I were you, a function should always either return a promise or not. Not doing so is an inconsistent interface in my opinion since calling it should always represent an asynchronous operation. – Benjamin Gruenbaum Commented Jul 30, 2014 at 9:37
  • @BenjaminGruenbaum check the edit, you mean like that? – Bobby B Commented Jul 30, 2014 at 11:45
  • This is definitely not what I meant. I meant I would not return undefined. qux should always return a promise and the type of promise should depend on what it does. Like in your initial version (the else is redundant). – Benjamin Gruenbaum Commented Jul 30, 2014 at 11:47
 |  Show 3 more ments

2 Answers 2

Reset to default 7

If you are going to use it with $.when you don't need to return an empty promise. $.when can handle non promises. Demo.

function promise(flag) {
    if(flag) {
        var dfd = $.Deferred();
        setTimeout(function(){
            console.log('promise');
            dfd.resolve();
        }, 1000);
        return dfd.promise();
    }

    console.log('promise');
}

$.when(promise(), promise(true), promise(), 15).done(function(){
    console.log('Done');    
});

And if you want to return an empty promise you can use $.Deferred().resolve().promise()

If your function is always synchronous - simply do not return a promise:

function qux() {
  if (something) {
    return $(".whatever")
      .removeClass("bob")
      .addClass("fred")
      .append(/*...do stuff...*/);
  }
}

You can still use it in $.when but there is little point since it executes synchronously. You should not return promises from synchronous functions.

However, if your function is sometimes synchronous - it should always return a promise for consistency.

As I said in earlier ments - $.when is perfectly fine with non-promises (it will treat them as promises). So functions that might return promises can be used with $.when however if it is always synchronous it is redundant to do so.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>