gpt4 book ai didi

javascript - 在返回之前等待异步完成

转载 作者:行者123 更新时间:2023-11-30 17:31:37 26 4
gpt4 key购买 nike

此代码返回一个配置对象,并最终用 knockout 的可观察对象填充它。

define("config", [], function () {
var config = {};
$.ajax({
url: "api/Config",
success: function (result) {
for (pname in result)
config[pname] = ko.observable(result[pname]);
},
});
return config;
});

它的工作原理是使用设置填充配置对象,但直到我的一个 View 应用绑定(bind)后它才会完成,这会导致运行时出现问题。

在返回配置对象之前,您将如何设置它以等待 ajax 查询的结果?我的第一个想法是使用 promise 对象,但我不知道如何应用它。

我不是在寻找解决方法,我已经有了一个:

define("config", [], function () {
var config = {
IsReady: ko.observable()
};
$.ajax({
url: "api/Config",
success: function (result) {
jquery.extend(config, result);
config.IsReady(true);
},
});
return config;
});

有了这个设置,我像这样绑定(bind)

<img data-bind="attr: { src: config.IsReady() ? config.Logo : '' }" />

但我不想让那些垃圾污染我的 View ,所以我想知道如何在从工厂方法返回之前等待异步操作。

尝试应用到目前为止收到的建议,我把事情搞得一团糟。因为 result 现在在范围内并且可以在调用 define 时使用,所以我直接将它传递给 define。

$.ajax({
url: "api/Config",
success: function (result) {
define("config", [], result);
}
});

//the following code should not execute until config has been defined.

define(['durandal/system', 'durandal/app', 'durandal/viewLocator'],
function (system, app, viewLocator) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");

app.title = 'Jumbo File Transfer';

app.configurePlugins({
router: true,
dialog: true,
widget: true
});

app.start().then(function () {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();

//Show the app by setting the root view model for our app with a transition.
app.setRoot('viewmodels/shell', 'entrance');
});
});

这会运行,但留下了如何让应用程序的其余部分等待直到这发生的问题。所以我将 main.js 的其余部分放在成功函数中,就像这样。

$.ajax({
url: "api/Config",
success: function (result) {
define("config", [], result);
define(['durandal/system', 'durandal/app', 'durandal/viewLocator'],
function (system, app, viewLocator) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");

app.title = 'Jumbo File Transfer';

app.configurePlugins({
router: true,
dialog: true,
widget: true
});

app.start().then(function () {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();

//Show the app by setting the root view model for our app with a transition.
app.setRoot('viewmodels/shell', 'entrance');
});
});
}
});

这实际上确实以正确的顺序执行 - 我逐步完成了它。但是应用程序无法启动。如果非要我猜原因的话,我会说 define 希望 this 成为全局上下文。

Nathan 在下面的回答并没有阻止 Durandal 正常启动,但是配置定义的行为不太正确。我需要将配置定义为一个充满设置属性的对象,而不是一个带有工厂方法的对象。但我们快到了。它只需要看起来像这样:

define('configFactory', ['plugins/http'], function (http) {
"use strict";
var getConfig = function () {
return http.get("api/Config").then(function (data) { return data; });
};
return { getConfig: getConfig };
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'configFactory'],
function (system, app, viewLocator, configFactory) {

//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");

app.title = 'Jumbo File Transfer';

app.configurePlugins({
router: true,
dialog: true,
widget: true
});

configFactory.getConfig().then(function (config) {
define('config', [], config);
app.start();
}).then(function () {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();

//Show the app by setting the root view model for our app with a transition.
app.setRoot('viewmodels/shell', 'entrance');
});
});

事后看来

您可以通过将 async 选项设置为 false 来制作 ajax block ,就像这样。

var foo;

$.ajax({
url:"whatever",
async: false
}).done(function(result){
foo = result;
});

//code that needs result

但是,引入瓶颈很少是个好主意。

这是根本问题:下面的代码将失败,因为在第一次渲染通过之前配置没有属性 foo

<span data-bind="text:config.foo"><span>

我们可以在 main 中同步加载配置,但更好的答案是推迟绑定(bind)直到 foo 可用。

<!-- ko if: config.foo -->
<span data-bind="text:config.foo"><span>
...
<!-- /ko -->

您不需要在 foreach 绑定(bind)的模板中像这样显式,因为模板是为每个实例呈现的。您只需预先声明 observableArray

最佳答案

我建议使用 http plugin在 durandal 中处理这个问题。

define(['plugins/http', 'services/logger'], function (http, logger) {
"use strict";
var getConfig = function () {
return http.get("api/Config").then(function (data) {
return data;
});
};
return {
getConfig: getConfig
};
});

接下来就是做事了

define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'config'], 
function (system, app, viewLocator, config) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");

app.title = 'Jumbo File Transfer';

app.configurePlugins({
router: true,
dialog: true,
widget: true,
http: true
});

config.getConfig().then(app.start()).then(function () {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();

//Show the app by setting the root view model for our app with a transition.
app.setRoot('viewmodels/shell', 'entrance');
});
});

编辑
我认为您只需要添加您在 ajax 调用的 done 函数中的内容即可获得您需要的内容。

define('configFactory', ['plugins/http'], function (http) {
"use strict";
var getConfig = function () {
return http.get("api/Config").then(function (data) {
var config = {};

for (pname in data){
config[pname] = ko.observable(data[pname]);
}

return config;
});
};
return { getConfig: getConfig };
});

关于javascript - 在返回之前等待异步完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22951407/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com