如何从 svelte 在 javascript 中单击按钮时调用异步函数?

How to call an async function on button click in javascript from svelte?

以下示例来自svelte官方文档

<script>
    async function getRandomNumber() {
        const res = await fetch(`tutorial/random-number`);
        const text = await res.text();
        if (res.ok) {
            return text;
        } else {
            throw new Error(text);
        }
    }
    
    let promise = getRandomNumber(); -------------- How does this work?

    function handleClick() {
        promise = getRandomNumber();
    }
</script>

<button on:click={handleClick}>
    generate random number
</button>

{#await promise}
    <p>...waiting</p>
{:then number}
    <p>The number is {number}</p>
{:catch error}
    <p style="color: red">{error.message}</p>
{/await}

我的问题是,当我们像上面那样将 'promise' 分配给函数 'call' 时,它应该立即调用该函数。在 svelte repl 中,这不会发生,随机数仅在单击按钮时生成。但是,当我修改代码以从简单的快速服务器获取 json 时,我什至不需要单击按钮 - 在应用程序启动时调用服务器。 (这是你所期望的)。发生了什么魔法?

虽然可能不重要,但这是我试过的代码。

<script>
        async function getNotes() {
        const res = await fetch('http://localhost:3001/api/notes')
        const json = await res.json()
        
        if(res.ok) {
            return json;
        } else {
            throw new Error(res)
        }
        
    }

    let promise = getNotes();
    
     function onClickGetNotes() {
        promise =  getNotes();
    }

</script>



<div class="grid-item-container card">

  
   <button on:click={onClickGetNotes}> Get Notes </button>

   {#await promise}
       .. Loading notes
   {:then notes} 
        
   {#each notes as note (note.id)}
       <div class="grid-item-container card">
          <p class="grid-item"> ID is {note.id} </p>
          <p class="grid-item"> Content is {note.content} </p>
          <lable class="grid-item" for="important"> Important 
            <input class="grid-item" type="checkbox" id="important" checked={note.important}>
          </lable>   
       </div>
   {/each}
    {:catch error}
    <p style="color: red">{error.message}</p>
   {/await}

</div>

调用异步函数以便仅在单击按钮时获取 json 的最佳方法是什么?

当我将您的代码按原样复制到 REPL 中时,数字会立即生成并在单击按钮时生成。这是意料之中的事情,确实应该发生。

What is the best way to call the async function so that the json is only fetched on button click?

好吧,在你需要它之​​前不要调用它。如果不是您想要的,则不在组件创建时。你可以简单地拥有:

    let promise

这将显示“号码未定义”。

如果您只想在发生某些事情时显示文本,您可以将其包装成 if

<button on:click={handleClick}>
  generate random number
</button>

<button on:click={() => { promise = null }}>
  reset
</button>

{#if promise != null}
  {#await promise}
    <p>...waiting</p>
  {:then number}
    <p>The number is {number}</p>
  {:catch error}
    <p style="color: red">{error.message}</p>
  {/await}
{/if}

或者如果你愿意,你可以给你的变量一个非 Promise 初始值:

    let promise = 0

如果你愿意,甚至是一个承诺:

    let promise = Promise.resolve(42)

只是添加这个供我参考。这就是我在 Rix 回答之前所做的事情。

<script>

let notes = []

async function getNotes() {

     const res = await fetch('http://localhost:3001/api/notes')
     const json =  await res.json()
     notes = json
    
     console.log('notes', notes)
    }
    
    async function onClickGetNotes() {
        await getNotes()
    }

</script>



<div class="grid-item-container card">

    <h4 class="grid-item"> Find the best</h4>

   <label class="grid-item" for="site-search">Suburb or Postcode</label>
   
   <input class="grid-item" type="search" id="site-search" name="q">
   
   <button on:click={onClickGetNotes}> Get Notes </button>

        
   {#each notes as note (note.id)}
       <div class="grid-item-container card">
          <p class="grid-item"> ID is {note.id} </p>
          <p class="grid-item"> Content is {note.content} </p>
          <lable class="grid-item" for="important"> Important 
            <input class="grid-item" type="checkbox" id="important" checked={note.important}>
          </lable>   
       </div>
   {/each}
    

</div>