Jak wyciągnąć zmienną na zewnątrz funkcji ?asynchronicznej?

0

Chcę wczytać dane z pliku tekstowego aby potem je rozprowadzić po formularzu w odpowiednie rubryki (taka funkcja wczytywania kopii roboczej).
Znalazłem skrypt, który na moje potrzeby będzie super ale jest jeden problem, pewnie kuriozalny. Skrypt pobiera dane z pliku i wrzuca treść do diva, podczas gdy ja potrzebuję zapisać je do zmiennej, którą mógłbym wykorzystać w innych funkcjach w ramach tego programu. Zakładam, że problemem jest asynchroniczność funkcji..

<head>
  <script>
    var openFile = function(event) {
      var input = event.target;

      var reader = new FileReader();
      reader.onload = function(){
        var text = reader.result;
        var node = document.getElementById('output'); //tutaj jest problem jak domniemam
        node.innerText = text;
        console.log(reader.result.substring(0, 200));
      };
      reader.readAsText(input.files[0]);
    };
  </script>
  </head>
  <body>
  <input type='file' accept='text/plain' onchange='openFile(event)'><br>
  <div id='output'>
  ...
  </div>
  </body>
  </html>

Lub z tego:

<head>
  <script>
	document.querySelector("#read-button").addEventListener('click', function() {
		let file = document.querySelector("#file-input").files[0];
		let reader = new FileReader();
		reader.addEventListener('load', function(e) {
	    		let text = e.target.result;
	    		document.querySelector("#file-contents").textContent = text;
		});
		reader.readAsText(file);
	});
  </script>
</head>
<body>
<input type="file" id="file-input" />
<button id="read-button">Read File</button>
<pre id="file-contents"></pre>
</body>
 </html>

2

Deklarujesz sobie text bez var na początku i masz zmienną globalną. Zasadniczo nie polecane z uwagi na potencjalne konflikty nazw z innymi skryptami, ale w małym projekcie może się sprawdzać.

Używasz return text; i zamiast zmiennej używasz, gdzie trzeba, samej funkcji. Sensowne jeśli nie musisz jej wywoływać wielokrotnie, licząc w kółko to samo.

0

@Freja Draco: Przepraszam ale nie rozumiem uczę się od 2 tygodni. Udało mi się zrobić więcej niż się spodziewałem. Praktycznie wszystko w ramach maleńkiego projektu, który był moim marzeniem, ale tej jednej rzeczy nie mogę przeskoczyć.

Czy mógłby ktoś na przykładzie pokazać co muszę zmodyfikować aby moja zmienna przyjmowała wartość wczytanego z pliku tekstu?

<head>
  <script>
     var openFile = function(event) {
       var input = event.target;

       var reader = new FileReader();
       reader.onload = function() {
         var text = reader.result;
         var node = document.getElementById('output'); //tutaj jest problem jak domniemam
         node.innerText = text;
         console.log(reader.result.substring(0, 200));
       };
       reader.readAsText(input.files[0]);
     };

   function danetupotrzebne()

   {
     var zmienna = xxxxx
   } 
 </script> 
</head>



<body>
  <input type='file' accept='text/plain' onchange='openFile(event)'><br>
  <div id='output'> </div>
  <input type="submit" value="LetsGo" onclick="function()" />

</body>

4

Nie możesz "wyciągnąć" zmiennej z funkcji asynchronicznej - cały Twój zależny kod musi być:
a) wywoływany w callbacku FileReadera, lub
b) FIleReader zwraca Promise, i uzywasz tego Promisa w dalszych funkcjach (zamiast bezpośrednio wartości), lub
c) użyć jeszcze innej techniki radzenia sobie z asynchronicznością (strumienie, kolejki itp).

Ogólnie jak raz użyjesz wywołania asynchronicznego, to cały zależny kod musi to uwzględniać.

Wersja z callbackami (bo żeby zrozumieć Promisy itp. to musisz najpierw zrozumieć callbacki):

<input type='file' accept='text/plain' onchange='openFile(event)'><br>
<div id='output'> </div>
function openFile (event) {
  const input = event.target;
  const reader = new FileReader();

  reader.onload = () => {
    const text = reader.result;

    // Call all dependent funtions:
    displayText(text);
    useText(text);
    // ...etc
  };

  reader.readAsText(input.files[0]);
};

function displayText(text) {
  const node = document.getElementById("output");
  node.innerText = text;
}

function useText(text) {
  //...use text
  console.log(text.slice(0, 100))
}

Możesz sobie oczywiście opakować zależne funkcje w jedną zbiorczą i ją wywołać w reader.onload:

function go(text) {
  displayText(text)
  useText(text)
}

Demo: https://codepen.io/caderek/pen/yLoVByb?editors=1011

1 użytkowników online, w tym zalogowanych: 0, gości: 1