【问题标题】:jQuery deferred promisejQuery 延迟承诺
【发布时间】:2014-08-27 07:29:44
【问题描述】:

下面的代码没有按预期工作。这里的 GetAllFileNames 是异步函数,我想根据这个函数的结果执行一些顺序操作。所以我正在使用 Jquery 承诺。但我觉得语句 return deferred.resolve(GetAllFileNames) 不正确。它立即调用 promise.then 甚至不等待 GatAllFileNames 完成。请注意这实际上不是工作代码。

function getfilenames() {
  var deferred = $.Deferred();

  if(condition == true) {
    return deferred.resolve(JSON.parse(allFileNames));
  } else {
    return deferred.resolve(GetAllFileNames());
  }
}    

var promise = getfilenames();      
promise.then(function(fileNames) {
  result.fileNames = fileNames; 
});

更新:我尝试了你的一些 cmets,但它们都没有工作。这是一个不工作的例子

<!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function () {
    var deferred = $.Deferred();
    var result = {};
    var GetAllFileNames = function () {
        return {
            "allFileNames": [1, 2, 3, 4, 5, 6, 7, 8, 9]
        };
    };

    function getfilenames(condition) {

        if (condition == true) {
            return deferred.notify(JSON.parse(allFileNames));
        } else {
            return deferred.notify(GetAllFileNames());
        }
    };

    deferred.then(
    // `deferred.done`
    function (fileNames) {
        result.fileNames = fileNames;
        $("<span>" + result.fileNames.allFileNames + "</span>")
            .appendTo("body");          console.log(JSON.stringify(fileNames));
    }
    // `deferred.fail`
    ,


    function () {
        console.log(new Error("getfilenames error").message);
    } );

    getfilenames(false);

}) </script> </head> <body>

</body> </html>

【问题讨论】:

  • 确认GetAllFileNames()是否完整的方法是什么?是否有要查询的项目的length 属性?如果任务要在GetAllFileNames() 之后执行,可以使用deferred.notify 提供GetAllFileNames() 和deferred.progress 的通知,然后resolve deferred 在progress 内完成时;然后调用deferred.then
  • 只做function getfilenames() { return condition ? $.when(JSON.parse(allFileNames)) : GetAllFileNames(); } 为什么这么麻烦?为什么要延期?为什么要下决心?这是做一些简单的事情的一种非常混乱的方式。
  • @Alien01 不确定if 语句的逻辑? ,condition 是什么? ,或者getallfilenames 的预期返回值是多少?由 condition 组成 false ;不确定getallfilenames 可能的返回值; allFileNames 是什么,如果在 getallfilenames 内通过函数返回?见帖子
  • @BenjaminGruenbaum 不错!另见$.when(condition ? getfilenames() : GetAllFileNames())
  • @guest271314 更好(并且更接近我通常所做的):) 您应该编辑您的答案以摆脱 deferred anti pattern

标签: jquery promise


【解决方案1】:

您应该在实际执行操作时解决延迟问题。

在此Example 中,“获取所有文件”将显示在“获取所有文件”之前

获取所有文件名
获取所有文件名

function GetAllFileNames(ms) {
    //simulate delay
    setTimeout( function() { console.log('Get all files names') ; return 20;}, ms);
} 

function getfilenames() {

    var def = $.Deferred();

    def.resolve(GetAllFileNames(2000));

    return def;
}

getfilenames().then( function() { console.log('Got all file names'); });

但here 控制台日志顺序将是

获取所有文件名
获取所有文件名

function GetAllFileNames(ms, def) {
    setTimeout(function() {
        console.log('Get all file names');
        def.resolve();
        return 20;
    }, ms);
}

function getfilenames() {

    var def = $.Deferred();

    var result = GetAllFileNames(2000, def);

    return def;
}

getfilenames().then(function() {
    console.log('Got all file names');
});

因为当 GotAllFilesNames 准备好时,defered 被解析。

【讨论】:

  • 你永远不应该编写一个需要延迟来实现的函数 - 只需将它们合并为一个。这也会使差异更加明显,在这里有点难以发现。
  • @Bergi,感谢您的注意。我认为以这种方式进行演示很容易,但请您解释一下,为什么不应该这样做?我会调整演示。
  • 它在一些罕见的设置中可能会有所帮助,但通常您只是将一个功能扩展到两个功能。 getfilenames 并没有做太多事情,创建 promise 应该是实际执行异步调用的函数的一部分。
  • 再次感谢,但我认为你用“不应该”声明指出了一个很大的缺点。无论如何,它是例如演示而不是实际的 getallfilenames 实现。关于解决延迟,这就是我在回答中所说的。
【解决方案2】:

编辑,更新;请参阅问题中的 cmets

试试(这个模式)

 var result = {};
 var GetAllFileNames = function () {
        return {
            "allFileNames": [1, 2, 3, 4, 5, 6, 7, 8, 9]
        };
    };
var getfilenames = function (condition) { // `condition` ?
    return $.when(
             condition 
             ? JSON.parse(allFileNames)
             : GetAllFileNames()
           ); 
    };

    getfilenames(false) // `condition` ?
    .then( 
    // `done`
      function (fileNames) {
        result.fileNames = fileNames;
        $("<span>" + result.fileNames.allFileNames + "</span>")
            .appendTo("body");
    }
    // `fail`
    , function () {
        console.log(new Error("getfilenames error").message);
    });

jsfiddle http://jsfiddle.net/guest271314/9f12san7/

【讨论】:

  • 你为什么(尝试)使用进度通知来解决延迟问题?
  • 要求澄清的问题应该放在原始帖子的 cmets 中,而不是答案中。
  • @Bergi 发现利用 deferred.notify 和 deferred.progress 进行“轮询”或中间任务的模式,实用。这些方法在 SO Questions 中似乎很少使用。只是一个模式; progress 可以运行多次而不实际解决 deferred 。如果提供给 notify-progress 的参数满足条件,则解决 deferred ,那里。利用进度回调通知进度“事件”的问题? ,在实际解决或拒绝延期之前?模式是否存在潜在问题?如果可能的话,能说明原因吗?
  • @Bergi 已更新。试图在初始帖子中包含有关如何到达 Answer 的详细信息/描述。谢谢
  • 当 getfilenamesis 在 true 条件下调用时,这不起作用,getfilenames(true)
猜你喜欢
  • 2015-03-27
  • 2023-03-21
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-10
  • 2019-04-26
相关资源
最近更新 更多