jQuery中如何让$.done()回调触发两次及异步请求回调问题
解决你的jQuery异步回调多次触发问题
首先,先明确一个关键知识点:jQuery的Deferred对象的done()回调只会在对象被resolve()(完成)时触发一次。如果想要同一个回调被触发多次,你需要用到progress()回调,配合deferred.notify()来发送多次更新通知。
针对你的代码场景,我们一步步来修改:
1. 修复startAsyncRequest的返回值问题
你当前的startAsyncRequest函数没有返回任何Deferred对象,导致Part A中的$.when()其实是在处理一个undefined值,会立即执行一次done()回调,后续的异步结果完全无法触发它。所以首先要让这个函数返回一个可控的Deferred:
jQuery.extend({ startAsyncRequest: function(arg){ // 创建一个Deferred对象用于对外传递状态 var deferred = $.Deferred(); console.log(arg); $.when(makeAjaxRequest(arg)).done(function(result){ var taskid = result.taskid; var taskurl = "someurl" + taskid; // 假设这里的startProgressBar包含轮询taskurl的逻辑 // 我们需要在每次轮询到结果时通知外部 function pollTaskStatus() { $.get(taskurl).done(function(pollResult) { // 每次拿到轮询结果,用notify发送给外部 deferred.notify(pollResult); if (pollResult.hasOwnProperty("responseJSON") && pollResult.responseJSON.status === "completed") { // 任务完成时,resolve这个Deferred,表示最终完成 deferred.resolve(pollResult); } else { // 未完成则继续轮询 setTimeout(pollTaskStatus, 1000); } }); } pollTaskStatus(); }); // 返回Deferred的promise,避免外部直接修改状态 return deferred.promise(); } });
2. 修改Part A的回调绑定逻辑
现在startAsyncRequest返回了一个支持多次通知的Promise,你可以用progress()来监听每次的结果更新,用done()来监听最终完成的状态:
// 先获取promise对象 var requestPromise = $.startAsyncRequest(arg); // 抽离重复执行的逻辑为单独函数 function handleResult(result) { console.log(result); if (result.hasOwnProperty("responseJSON")){ console.log("build frontend table using completed task"); } } // 绑定progress回调,每次notify都会触发 requestPromise.progress(handleResult); // 绑定done回调,最终完成时触发(可选,如果你需要在完成时额外处理) requestPromise.done(handleResult);
如果你确实希望用$.when()的方式(虽然这里直接用返回的promise更简洁),也可以这样写:
$.when($.startAsyncRequest(arg)) .progress(function(result) { console.log(result); if (result.hasOwnProperty("responseJSON")){ console.log("build frontend table using completed task"); } }) .done(function(result) { // 可选:任务最终完成时的额外处理 console.log("任务完全结束", result); });
为什么不直接用done()触发多次?
因为jQuery的Deferred设计是一次性状态:一旦被resolve()或reject(),状态就固定了,不会再触发对应的done()或fail()回调。而progress()是专门用于传递中间更新的,可以被多次触发,完全匹配你“每次有结果返回都执行回调”的需求。
内容的提问来源于stack exchange,提问作者Kai Aeberli
相关产品推荐
相关产品推荐

