Windows Azure中的同步请求?

use*_*616 0 javascript azure azure-table-storage azure-mobile-services

因此,在我的服务器代码中,变量邀请在成功函数之外是未定义的.

function getInvites(id){
    var InvitesTable = tables.getTable("Invites").where({"PlanID": id}).select("UserID","Attending");
    var invites;
    InvitesTable.read({ success: function(resultss) { 
                           invites = resultss;
                           console.log(invites); //works here
                           }});
    console.log(invites); //undefined here
}
Run Code Online (Sandbox Code Playgroud)

从类似的问题,我意识到它是因为它是异步的.因此,调用后运行成功函数console.log(invites); //undefined here调用.

我的问题是如何在Windows Azure中停止它?

添加了代码

function read(query, user, request) {

        request.execute({
            success: function(results) {
                results.forEach(function(r) {

                    getInvites(r.id, function(invites) {
                        r.invites = invites;
                    });
                });
                request.respond();
            }
        });

}

function getInvites(id, cb){
    var InvitesTable = tables.getTable("Invites").where({"PlanID": id}).select("UserID","Attending");
    InvitesTable.read({ success: function(results) {
                           if (cb) cb(results);
                           }});
}
Run Code Online (Sandbox Code Playgroud)

jos*_*736 5

你没有"停止",你围绕你正在使用的任何环境的异步性质设计你的应用程序.

我假设你正在尝试做这样的事情:

function getInvites(id){
    var InvitesTable = tables.getTable("Invites").where({"PlanID": id}).select("UserID","Attending");
    var invites;
    InvitesTable.read({ success: function(resultss) { 
                           invites = resultss;
                           }});
    return invites;
}

// later...

var invites = getInvites(someId);
//do something with `invites`
Run Code Online (Sandbox Code Playgroud)

这显然不起作用,因为您invites在异步调用完成之前返回值.

相反,您以异步方式编写应用程序:

function getInvites(id, cb){
    var InvitesTable = tables.getTable("Invites").where({"PlanID": id}).select("UserID","Attending");
    InvitesTable.read({ success: function(resultss) { 
                           if (cb) cb(resultss);
                           }});
}

// later...

getInvites(someId, function(invites) {
    //do something with `invites`
});
Run Code Online (Sandbox Code Playgroud)

为简单起见,这省略了错误处理代码,因此您也必须添加它.


看到完整的代码后,看起来你有一个管理许多并行异步操作的简单问题.考虑一下发生了什么:你的循环运行,迭代n个对象的数组.对于每个,您调用getInvites,它开始一个数据库请求并返回.

这意味着您的循环运行速度非常快,但现在您有n个未完成的数据库请求,您必须等待才能调用request.respond().

一个非常基本的解决方案是做一些事情,比如计算你的getInvites回调被调用的次数,然后当该数字达到n时最终完成请求.

但是,每次发出异步请求时,手动管理此簿记都非常耗时且容易出错.这是流控制库非常有用的情况.我将Deferred在这个例子中使用jQuery ,因为它可能已经为你所熟悉(即使你以前不知道你实际使用过它 - 如果你曾经使用过jQuery的XHR API,你已经使用了Deferreds).

鉴于你在服务器环境中,你显然没有jQuery; 但是,有些人只提取Deferred了你需要的代码.

一旦我们Deferred为每个待处理请求提供了s,我们就可以使用when注册一个只在所有挂起Deferreds完成后才被调用的回调.

function read(query, user, request) {

        request.execute({
            success: function(results) {
                var dfds = [];
                for (var i = 0; i < results.length; i++) {
                    dfds.push(getInvites(results[i].id)); // Makes an array of Deferreds representing
                                                          // each of our pending requests.
                }


                Deferred.when.apply(Deferred, dfds) // see details below
                    .done(function() {
                        for (var i = 0; i < results.length; i++) {
                            results[i].invites = arguments[i]; // Copy each set of invites to each result
                        }
                        request.respond(); // We're done!
                    })
                    .fail(function() {
                        // Handle errors here
                    });
            }
        });

}

function getInvites(id){
    var dfd = new Deferred(); // Create a new Deferred, which automatically starts in the 'pending' state
    var InvitesTable = tables.getTable("Invites").where({"PlanID": id}).select("UserID","Attending");
    InvitesTable.read({ success: function(results) {
                           dfd.resolve(results); // When we get data back, we 'resolve' the Deferred --
                                                 // in other words, say its operation is done,
                                                 // and pass along the operation's results.
                           },
                        error: function(err) { // TODO: Not sure if this is how the API you're using handles errors
                            dfd.reject(err); // Marks the Deferred as failed.
                        }});

    return dfd.promise(); // We (synchronously) return the Promise.  The caller can attach event handlers
                          // to the Promise, which are invoked when we eventually resolve or reject the Deferred.
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • jQuery.when(或在此服务器端的情况下,Deferred.when)通常希望您传递固定数量的Deferreds作为参数:

    $.when(dfd1, dfd2).done(function(result1, result2) { ... });
    
    Run Code Online (Sandbox Code Playgroud)

    但是,我们有一个可变数量的Deferreds,所以我们必须有apply一个Deferreds 数组,when然后在done处理程序中,通过隐式arguments对象访问每个结果.

  • Array.forEach(...) 很慢.在大多数情况下,最好使用常规for循环.