草庐IT

javascript - 将回调变成 promise

coder 2024-12-09 原文

我正在使用 google maps api,这段代码异步返回地点列表。我怎样才能调用这个函数并让它在收集完所有数据后触发一些东西?到目前为止,这是我尝试过的 -

$.search = function(boxes) {

    function findNextPlaces(place_results, searchIndex) {
        var dfd = $.Deferred();
        if (searchIndex < boxes.length) {
            service.radarSearch({
                bounds: boxes[searchIndex],
                types: ["food"]
            }, function (results, status) {
                if (status != google.maps.places.PlacesServiceStatus.OK) {
                    return dfd.reject("Request["+searchIndex+"] failed: "+status);
                }
                console.log( "bounds["+searchIndex+"] returns "+results.length+" results" );
                for (var i = 0, result; result = results[i]; i++) {
                    var marker = createMarker(result);
                    place_results.push(result.reference); // marker?
                }
            });
            return dfd.then(findNextPlaces);
        } else {
            return dfd.resolve(place_results).promise();
        }
    }

    return findNextPlaces([], 0);
};

最佳答案

要回答标题所暗示的问题,“将回调转化为 promise ”,简单的答案是使用一个非常简单的“ promise 模式”(我的术语),其中 Deferred 的 .resolve() 方法被建立为回调:

带回调的原始调用:

obj.method(param1, param2, ... paramN, callbackFn);

转换后的调用,使用 Deferred 包装器:

$.Deferred(function(dfd) {
    obj.method(param1, param2, ... paramN, dfd.resolve);
}).promise();

无论 obj.method 是否异步,这都可以完成。优点是您现在可以在同一代码块中或更典型地在分配或返回生成的 Promise 的其他地方使用 Deferreds/promises 的完整链式。

在这个问题的情况下,可以使用这种模式......

$.search = function(boxes, types) {

    function findPlaces(box) {
        var request = {
           bounds: box,
           types: types
        };

        //***********************
        // Here's the promisifier
        //***********************
        return $.Deferred(function(dfd) {
            service.radarSearch(request, dfd.resolve);
        }).promise();
        //***********************
        //***********************
        //***********************
    }

    function handleResults(results, status, searchIndex) {
        var message, marker;
        if (status != google.maps.places.PlacesServiceStatus.OK) {
            message = "bounds[" + searchIndex + "] failed : " + status;
        }
        else {
            message = "bounds[" + searchIndex + "] returns " + results.length + " results";
            for (var i = 0, result; result = results[i]; i++) {
                marker = createMarker(result);
                place_Results.push(result.reference);
            }
        }
        return message;
    }

    var place_Results = [],
        p = $.when();//resolved starter promise

    //This concise master routine comprises a loop to build a `.then()` chain.
    $.each(boxes, function(i, box) {
        p = p.then(function() {
            return findPlaces(box).done(function(results, status) {
                // This function's arguments are the same as the original callback's arguments.
                var message = handleResults(results, status, i);
                $('#side_bar').append($("<div/>").append(message));
            });
        });
    });

    //Now, chain a final `.then()` in order to make the private var `place_Results` available via the returned promise. For good measure, the `types` array is also repeated back.
    return p.then(function() {
        return {
            types: types,
            results: place_Results
        };
    });
};

$.search() 现在可以按如下方式使用:

$.search(boxes, ["food"]).done(function(obj) {
    alert(obj.results.length + ' markers were a added for: "' + obj.types.join() + '"');
});

DEMO - 注意:由于 jQuery 1.8.3 对 jQuery.Deferred.then() 进行了重大修订,因此需要 jQuery 1.8.3+。

这并不完全等同于问题中的代码,但可能有助于诊断您报告的问题。特别是:

  • 它不会因错误而停止
  • 它将在“#side_bar”中放置成功和错误 消息。

调整代码来执行您想要的操作应该足够简单。

关于javascript - 将回调变成 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21967065/

有关javascript - 将回调变成 promise的更多相关文章

  1. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  2. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  3. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  4. ruby-on-rails - 将保存回调添加到单个 ActiveRecord 实例,可以吗? - 2

    是否可以为单个ActiveRecord实例添加回调?作为进一步的限制,这是继续使用库,所以我无法控制该类(除了对其进行猴子修补)。这或多或少是我想做的:defdo_something_creazymessage=Message.newmessage.on_save_call:do_even_more_crazy_stuffenddefdo_even_more_crazy_stuff(message)puts"Message#{message}hasbeensaved!Hallelujah!"end 最佳答案 你可以通过在创建对象后立

  5. ruby-on-rails - Ruby method_added 回调不触发包括模块 - 2

    我想写一点“Deprecate-It”库并经常使用“method_added”回调。但是现在我注意到在包含模块时不会触发此回调。是否有任何回调或变通方法,以便在某些内容包含到自身时通知类“Foobar”?用于演示的小Demo:#IncludingModulswon'ttriggermethod_addedcallbackmoduleInvisibleMethoddefinvisible"Youwon'tgetacallbackfromme"endendclassFoobardefself.method_added(m)puts"InstanceMethod:'#{m}'addedto'

  6. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  7. ruby-on-rails - 使用 before_save 回调或自定义验证器添加验证错误? - 2

    我有一个模型Listingbelongs_to:user。或者,Userhas_many:listings。每个列表都有一个对其进行分类的类别字段(狗、猫等)。User还有一个名为is_premium的bool字段。这是我验证类别的方式...validates_format_of:category,:with=>/(dogs|cats|birds|tigers|lions|rhinos)/,:message=>'isincorrect'假设我只想让高级用户能够添加老虎、狮子和犀牛。我该怎么做?最好在before_save方法中执行此操作吗?before_save:premium_che

  8. ruby - 如何将 Ruby 脚本变成 bash 命令? - 2

    我有一个Ruby文件,我将它作为rubyfile.rb"parameters"运行。我更喜欢将它作为regtask参数运行,而不必每次都包含ruby和文件名。我希望它与ls处于同一级别。我将如何做到这一点? 最佳答案 编辑你的文件,确保这是第一行,这样你的系统就知道如何执行你的文件:#!/usr/bin/envruby接下来,更改文件的权限以使其可执行:chmoda+xfile.rb最后,重命名并将其移动到将要执行的位置,而无需编写其完整路径:mkdir-p~/binmvfile.rb~/bin/regtask(如果~/bin存在,

  9. ruby-on-rails - 如何在多个环境中处理 OmniAuth 回调? - 2

    我有一个应用程序专门使用Facebook作为身份验证提供程序,并正确设置了生产模式的回调。为了让它工作,您需要为您的Facebook应用程序提供一个站点URL和一个用于回调的站点域,在我的例子中是http://appname.heroku.com和appname。heroku.com分别。问题是我的Controller设置为只允许经过身份验证的session,所以我无法在开发模式下查看我的应用程序,因为Facebook应用程序的域显然没有设置为本地主机。如何在不更改Facebook设置的情况下解决这个问题? 最佳答案 创建另一个域l

  10. ruby-on-rails - Rails 模型中的条件回调? - 2

    只是想知道是否有一种方法可以在Rails中进行条件回调。我知道您可以像这样进行条件验证:validates_uniqueness_of:email,:if=>(1==1)我经常在回调中做这样的事情:classLineItem稍微清理一下就好了。 最佳答案 classLineItem 关于ruby-on-rails-Rails模型中的条件回调?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/quest

随机推荐