Rufen Sie die Array-Variable aus dem Soliditätsvertrag in der Webanwendung auf

Ich habe ein Array innerhalb des Solidity-Vertrags wie „ uint256[] public machineList; “ deklariert und die Werte dieses Arrays innerhalb des Konstruktors initialisiert.

Aber wenn ich dieses Array innerhalb von js usgin web3 wie unten erwähnt aufrufe:

AssetContract.deployed().then(function(contractInstance) {

    let getMachineList = contractInstance.machineList;
    alert(getMachineList);
});

Es gibt die folgende Ausgabe in der Variablen getMachineList zurück:

    function () {
  var instance = this
  var args = Array.prototype.slice.call(arguments)
  var tx_params = {}
  var last_arg = args[args.length - 1]
  if (Utils.is_object(last_arg) && !Utils.is_big_number(last_arg)) {
    tx_params = args.pop()
  }
  tx_params = Utils.merge(C.class_defaults, tx_params)
  return C.detectNetwork().then(function () {
    return new Promise(function (accept, reject) {
      var callback = function (error, result) {
        if (error != null) {
          reject(error)
        } else {
          accept(result)
        }
      }
      args.push(tx_params, callback)
      fn.apply(instance.contract, args)
    })
  })
}

diese Art von Daten, die ich bekommealert(contractInstance.machineList);

Wie können wir also Array-Werte in Side JS erhalten, ohne eine explizite Getter-Funktion innerhalb von Solidity zu erstellen, anstatt die eingebaute Getter-Funktion aufzurufen, die von Solidity für die Zustandsvariable bereitgestellt wird?

Antworten (2)

Sie können ein dynamisches Array wie folgt erhalten: uint256[] public machineList , indem Sie eine Contract-Getter-Funktion erstellen.

function getMachineList () external returns (uint256[]){
return machineList
}

Beachten Sie den externen Modifikator, den ich hinzugefügt habe. Bei dieser Art von Funktionen, bei denen Sie ein Array mit dynamischer Größe zurückgeben, ist der externe Modifikator obligatorisch. Es macht die Funktion auch nur von außerhalb des Vertrags aufrufbar, was genau das ist, was wir hier wollen.

Eine andere Sache ist, dass Sie Truffle verwenden, um Vertragsfunktionen aufzurufen. Wenn Sie Trüffel verwenden, müssen Sie nach dem Namen der Funktion ein Versprechen (oder einen Rückruf) aufrufen :

AssetContract.deployed().then(function (contractInstance) {

  contractInstance.getMachineList.
  call(**arguments if any**,{ from:**address**, gas: 300000 }).then(
    data => {
      var MachineList = data;
      alert(MachineList);
    }
  )

})

Hinweis: Wenn Sie Trüffel verwenden, fügen Sie das hinzu .call(), wenn Sie nur Funktionen aufrufen, die Variablen lesen und zurückgeben, als ob sie Zustandsvariablen nicht ändern würden (vorhandenen/neuen Wert ändern/hinzufügen).

Ja, eigentlich ist Ihre Lösung richtig, ich habe bereits die Getter-Funktion erstellt, die dieses Array zurückgibt. und ich habe auch die richtigen Werte in der js-Datei so bekommen. contractInstance.getMachineList.call().then(function(machineId) { var temp = contractInstance.machineList; alert(temp); });
Aber der Punkt, den ich nicht verstanden habe, ist, dass, wenn wir ein Array zurückgeben, warum ich dann die Ausgabe so erhalten habe: 111, 112, 113,114,115,116 anstelle des Array-Objekts.
Tatsächlich habe ich später erfahren, dass in Solidität eingebaute Getter vorgesehen sind, deshalb habe ich die Lösung ausprobiert, die dort in Frage kommt
Ja, öffentliche Zustandsvariablen haben automatisch erstellte Getter, aber ich bin mir nicht sicher, ob Sie get auf ein öffentliches dynamisches Array aufrufen können und trotzdem die benötigten Werte erhalten. Aber die externe Getter-Funktion, die ich erwähnt habe, gibt die richtigen Werte und das richtige Format zurück, wenn Sie mehr Code und Ausgabe posten können, kann ich helfen, das zu klären.
Eigentlich habe ich dafür 2 Arrays initialisiert und möchte, dass die Array-Werte in der Dropdown-Box der Webanwendung enthalten sind. Das funktioniert also. Aber jetzt, wenn wir einige Werte aus beiden Dropdown-Feldern auswählen, möchte ich die Zuordnung dieser beiden ausgewählten Werte vornehmen.
Dafür habe ich diese Funktion in Smart Contract erstellt: function allocate(uint256 machineId,uint256 userId) public return (bool){ machineAllocs[machineId] = userId; //return machineAllocs[machineId]; if ( machineAllocs [machineId] == 0 ) { machineAllocs [machineId] = userId; gib true zurück; }sonst {falsch zurückgeben; } } Aber wenn ich diese Funktion von js aus aufrufe, wird [object object] erneut ausgeführt. Ich weiß nicht, wie ich das weiter machen soll.
In der Kontraentwicklung können Sie keine Funktion aufrufen, die Zustandsvariablen und Rückgabewerte ändert. Wenn eine Funktion den Status ändert, wird sie als Transaktion betrachtet und gibt keinen Wert zurück, stattdessen gibt sie die Transaktionsquittung zurück. Bei der Verwendung von Truffle oder Web3 gibt es einen Unterschied zwischen den beiden Arten des Aufrufs von Funktionen. Die Methode, die Sie aus Ihrem Vertrag aufgerufen haben, ändert die Zustandsvariable, wenn sie dem Smart Contract neue Daten hinzufügt, sodass sie keinen Wert zurückgibt, selbst wenn Sie dies returnin Ihrem Code erwähnen.
Ok, wenn ich auf eine Zustandsvariable einen wahren oder falschen Wert setze, dann bekomme ich den Wert dieser Variablen von der Getter-Funktion dieser booleschen Variablen. Also, wird das funktionieren oder nicht?
Ja, es sollte funktionieren, aber es ist einfach nicht wie Java, wo Sie eine Zustandsvariable ändern und den Wert in derselben Funktion zurückgeben können. Lesen und Schreiben sollten in separaten Funktionen erfolgen.
Das bedeutet, dass ich den Wert der Zuordnung in einer Funktion ändern und in einer anderen Funktion zurückgeben kann. Wird es funktionieren ?
siehe Ich habe zwei Funktionen im Vertrag: function getMachineAllocs(uint256 machineId) view public returns (uint256) { return machineAllocs[machineId]; } function allocate (uint256 machineId, uint256 userId) public { machineAllocs[machineId] = userId; } Und ich rufe sie so in der js-Datei auf: contractInstance.allocate(parseInt(machineId), parseInt(userId),{gas: 140000, from: web3.eth.accounts[0]}).then(function() { return contractInstance.getBoolean.call(parseInt(machineId)).then(function(c) und print c, es gibt den Wert 0 zurück. Warum ist das so?

Sie können nicht auf das gesamte Array zugreifen, ohne den Getter anzugeben. Sie können immer noch die eingebaute Funktion aufrufen, die von der publicZustandsvariablen bereitgestellt wird, aber Sie müssen den Index des Arrays angeben, um seinen Wert zu erhalten.

In der Tat würde Ihr ABI für das bereitgestellte Array ungefähr so ​​​​aussehen

{
    "constant": true,
    "inputs": [
        {
            "name": "",
            "type": "uint256"
        }
    ],
    "name": "machineList",
    "outputs": [
        {
            "name": "",
            "type": "uint256"
        }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
}

eine Eingabe wird erwartet und ist der Index des Elements des Arrays, das Sie lesen möchten.

Ja, wenn wir einen Index bereitstellen, gibt er den Werttyp [object Promise] zurück.