繁体   English   中英

无法从 ember js 中的 servlet 呈现 json 数组

[英]couldnt render a json array from servlet in ember js

我正在尝试渲染从 ember 中的 java servlet 发送的 json 数组。 工作流程如下

1.向servlet发送一个ajax请求,servlet将返回jsonobject

2.我会得到 json object 并尝试在车把文件中渲染

问题是当我安慰它带有索引的响应时

0: {CAPACITY: '4', PRICE: '918', RTYPE: 'basic', ID: '4'}
1: {CAPACITY: '2', PRICE: '885', RTYPE: 'villa', ID: '8'}
2: {CAPACITY: '2', PRICE: '1579', RTYPE: 'villa', ID: '5'}
3: {CAPACITY: '1', PRICE: '1526', RTYPE: 'villa', ID: '1'}

但是服务器发送的是

{"CAPACITY":"4","PRICE":"918","RTYPE":"basic","ID":"4"}
{"CAPACITY":"2","PRICE":"885","RTYPE":"villa","ID":"8"}
{"CAPACITY":"2","PRICE":"1579","RTYPE":"villa","ID":"5"}
{"CAPACITY":"1","PRICE":"1526","RTYPE":"villa","ID":"1"}

controller 代码

export default class RoomselectController extends Controller {
    @service router;
    @tracked obj = null  ;
    @tracked price =0;
    get res(){
        var dis = this;
        const mobile = "123123123";
        $.ajax({
            url:'My',
            method : 'GET',
            dataType:'json',
            data : {mobile:mobile},
            success:function(response){
                console.log(response);
                dis.price = response[0].PRICE;//when rendered this works
                dis.obj = response;//when changed to dis.obj = response[0] it renders the first
                
                return response[0];
            },
            error: function(xhr,status,error){
                var errorMessage = xhr.status + ": " + xhr.statusText;
                alert("error " + errorMessage);
            }
        })
    }

.hbs 代码

<table border ="1">
    <tr><td><b>Capacity</b></td><td><b>Price</b></td><td><b>Room Type</b></td><td><b>Room No</b></td></tr>

    
    {{#each-in this.obj as |key value|}}    
    <td>{{value}}</td>
    {{/each-in}}

    </table>

它不工作,但是当我使用dis.obj = response[0]它工作并只呈现第一个索引如何使它呈现每个数据?

JS + 反应性中的异步有点不重要——但是。 有许多抽象可以提供帮助。

这里有一个视频/谈话,讨论了这个问题,以及解决它的各种方法:“什么是最困难的时间?关于异步? ”——Jim Schofield,Emberconf 2022

要点如下:

  • 吸气剂永远不应该引起副作用( this吸气剂中设置任何东西)
  • getter 永远不应该返回 Promise。

关于我在您的代码中看到的一些注释:

  • getter res永远不会被访问,因此它无法运行。
  • getter res不返回任何东西,所以访问它没有意义——现代 ESLint 配置中有一个 lint 会抱怨 getter 不返回任何东西
  • 影响发生在 getter 中,这使得组件的整体 state 不稳定 - 请记住,每次访问 getter 时都会重新运行它的内容 - 所以如果您有多个访问this.res的东西,您将创建新的 ajax每次访问的请求。
  • 该模板遍历 object,但忽略了响应数组中的其他条目——不确定是否有意,但在下面的代码中,我假设您要遍历响应中的所有条目。

但! 将其转换为

  • 模型异步生命周期(加载、成功、错误等)
  • 反应性地为您提供上述状态,并为您提供一些可迭代的内容(您最终希望在模板中对each-in输入执行此操作。

我最喜欢的方法是使用Resource

使用库ember-resources提供的实用程序有几种方法可以实现您想要的功能。

使用实用程序, trackedFunction

这是一个包装 Resource 原语并提供一些 异步 state的实用程序。

您使用此实用程序的代码如下所示:

import { trackedFunction } from 'ember-resources/util/function';

export default class RoomselectController extends Controller {
    @service router;

    request = trackedFunction(this, async () => {
      const mobile = '123123123';
    
      // I'm constructing a custom promise here
      // because I don't know if your $.ajax supports async/await
      return new Promise((resolve, reject) => {
        $.ajax({
          url: 'My',
          method: 'GET',
          dataType: 'json',
          data: { mobile },
          success: (response) => resolve(response),
          error: (xhr, status, error) => reject(`${status}: ${xhr.statusText}`),
        });
      });
    });

    get result() {
      return this.request.value || [];
    }

}
{{#if this.request.isPending}}
  loading data...
{{/if}}

<table border ="1">
  <thead>
    <tr>
      <th>Capacity</th>
      <th>Price</th>
      <th>Room Type</th>
      <th>Room No</th>
    </tr>
  </thead>
  <tbody>
   
    {{#each this.result as |row|}}    
      <tr>
        {{#each-in row as |key value|}}
          {{value}}
        {{/each-in}}
      </tr>
    {{/each}}
  </tbody>
</table>

使用自定义Resource

第二种方法是使用您自己的 state,由您创建并在自定义resource中使用。

使用相同的模板,您可以实现这样的自定义资源:

import { use, resource } from 'ember-resources';
import { tracked } from '@glimmer/tracking';

class RequestState {
  @tracked value;
  @tracked error;

  get isPending() {
    return !this.error && !this.value;
  }
}

export default class RoomselectController extends Controller {
    @service router;

    @use request = resource(({ on }) => {
      const mobile = '123123123';
      const state = new RequestState();
    
      $.ajax({
        url: 'My',
        method: 'GET',
        dataType: 'json',
        data: { mobile },
        success: (response) => state.value = response;,
        error: (xhr, status, error) => state.error = `${status}: ${xhr.statusText}`,
      });

      return state;
    });

    get result() {
      return this.request.value || [];
    }

}

参考

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM