简体   繁体   English

如何将异步 function 的返回值分配给变量

[英]how do I assign a returned value from an async function to a variable

I am new to JavaScript and have been trying to read up a lot on why this is not working.我是 JavaScript 的新手,并且一直在尝试阅读很多关于为什么这不起作用的信息。 Here is my code.这是我的代码。 I have also read a number of articles here on stack overflow but still feeling dense我也在这里阅读了一些关于堆栈溢出的文章,但仍然感觉很密集

Also if my title does not make sense, please suggest an edit另外,如果我的标题没有意义,请提出修改建议

 listRef.listAll()
            .then(response => {
                let files = []  
                response.items.forEach(item => {
                    
                  var text
                  getText(item.name).then(res=>{text = res});
                    
                    const id = {uid: guid()}
                    const url = item.getDownloadURL().then(url => {return url} )
                    const gsurl = `gs://archivewebsite.appspot.com/${folder}/${item.name}`
                    files.push({...item, name:item.name, url, gsurl, id:id.uid, text})
                
                    });
                    this.files = files;
                  })
            .catch(error => console.log(error));


  async function getText(docID) {
        var docRef = firestore.collection("recipes").doc(docID);
        let doc = await docRef.get()
        if (doc.exists){
           return doc.data().text
         }
}

that code "works" in that it logs the response to the console but the text variable is a pending promise object.该代码“有效”,因为它将响应记录到控制台,但文本变量是待定的 promise object。

I understand that async functions return a promise so when I call getText I need to use.then - what I am struggling with and have refactored this code a few times is this: how can I assign the value of doc.data().text to a variable to be used later in other words, how can var text be an actual string and not a promise object pending我知道异步函数返回 promise 所以当我调用 getText 时我需要使用。然后 - 我正在努力解决并重构了这段代码几次的是:我如何分配 doc.data().text 的值到以后要使用的变量,换句话说,var text 如何成为实际字符串而不是 promise object pending

Also for my own learning on javascript inside the async function if I replace如果我更换,也用于我自己在异步 function 内的 javascript 上学习

if (doc.exists){
           return doc.data().text
         }

with

 if (doc.exists){
           return Promise.resolve(doc.data().text)
         }

I get the same result in console.log - is this expected?我在 console.log 中得到相同的结果 - 这是预期的吗? is return simply short hand for the handler to resolve the promise? return 只是处理程序解析 promise 的简写吗?

I have also refactored this code to be non async and I get the same result where my var text is basically a pending promise and never the resolved data我还将此代码重构为非异步代码,我得到了相同的结果,其中我的 var 文本基本上是待处理的 promise 而不是已解析的数据

Thanks for your help - also any articles to help explain this to me would be great!感谢您的帮助 - 任何有助于向我解释这一点的文章都会很棒! I have been going through courses on udemy but little confused by this right now我一直在学习关于 udemy 的课程,但现在对此有点困惑

Actually you are assigning the complete promise to the variable text实际上,您正在将完整的 promise 分配给变量文本

Replace代替

var text = getText(item.name).then(res=>console.log(res))

by经过

var text = await getText(item.name);

OR要么

var text
getText(item.name).then(res=>{text = res});

Of course text is going to be a Promise .当然text将是Promise Promise.then() always returns a Promise . Promise.then()总是返回Promise

Consider this code:考虑这段代码:

function doA(n) {
  // do something here...
  console.log("A" + n);
}
asnyc function doB(n) {
  // do something here...
  console.log("B" + n);
}

doA(1);
doA(2);
doB(3); // async
doA(4);
doB(5); // async
doB(6); // async
doA(7);

What do you expect the output to be?您期望 output 是什么?

  • 1, 2, 4, and 7 will always be in order, because they are executed synchronously. 1、2、4、7永远是有序的,因为它们是同步执行的。
  • 3 will not ever print before 1 and 2. Likewise, 5 and 6 will not ever print before 1, 2, and 4. 3 永远不会在 1 和 2 之前打印。同样,5 和 6 永远不会在 1、2 和 4 之前打印。
  • However, 3, 5, and 6 can be printed in any order, because async functions do not guarantee execution order once created.但是,3、5 和 6 可以按任何顺序打印,因为异步函数一旦创建就不能保证执行顺序。
  • Also, 4 can print before 3. Likewise, 7 can print before 5 and 6.此外,4 可以在 3 之前打印。同样,7 可以在 5 和 6 之前打印。

Basically, think of async functions as a parallel task that runs independently (although not really; single thread JS only simulates this behavior).基本上,将异步函数视为独立运行的并行任务(虽然不是真的;单线程 JS 仅模拟此行为)。 It can return (fulfill/reject) at any moment.它可以随时返回(履行/拒绝)。 For this reason, you cannot just simply assign a return value of an async function to a variable using synchronous code - the value is not guaranteed to be (and probably is not) available at the moment of synchronous execution.出于这个原因,您不能简单地将异步 function 的返回值分配给使用同步代码的变量 - 该值不能保证(并且可能不)在同步执行时可用。


Therefore you need to put all the code that requires the value of text to be set into the callback block of the Promise , something like this:因此,您需要将所有需要设置text值的代码放入Promise的回调块中,如下所示:

getText(item.name).then((text) => {
  // put everything that uses text here
});

This can of course lead to the infamous "callback hell", where you have layers inside layers of async callback.这当然会导致臭名昭著的“回调地狱”,在异步回调层中有层。 See http://callbackhell.com for details and mitigation techniques.有关详细信息和缓解技术,请参阅http://callbackhell.com

async/await is just one of the newer ways to do the same thing: MDN has an excellent article here: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await async/await只是做同样事情的新方法之一:MDN 在这里有一篇很棒的文章: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

OK I worked with someone at work and found a solution - it was related to this post https://stackoverflow.com/a/37576787/5991792 I was using async function inside a for each loop好的,我在工作中与某人一起工作并找到了解决方案 - 它与这篇文章https://stackoverflow.com/a/37576787/5991792有关 我在每个循环中使用异步 function

the refactored code is here重构代码在这里

async function buildFiles(){
  let items = await listRef.listAll()
  let files = []
  for (const item of item.items){
    const text = await getText(item.name)
    const url = await item.getDownloadURL()
    const gsurl = `gs://archivewebsite.appspot.com/${folder}/${sermon.name}`
    files.push({...item, name:item.name, url, gsurl, text})  
}
return files
}


 async function getText(docID) {
        var docRef = firestore.collection("recipies").doc(docID);
        let doc = await docRef.get()
        if (doc.exists){return await doc.data().text}}



buildFiles().then(res=>this.files = res)

Thanks also to @cyqsimon and @Nav Kumar V还要感谢@cyqsimon 和@Nav Kumar V

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

相关问题 如何将异步 function 返回的 object 分配给变量 - How to assign an object returned by an async function to a variable 如何将侦听器中 function 的返回值分配给变量并将其拆分 - how to assign a returned value from a function in a listener to variable and split it Typescript:从Async函数为变量赋值 - Typescript: Assign value to variable from Async function 如何将函数返回的值分配给变量? - How to assign value returned by a function into a variable? 如何分配从匿名函数返回的值? - How can I assign value returned from anon function? 如何将值从异步方法返回的值发送到JavaScript中的另一个异步方法? - How do I send value from returned from async method to another async method in javascript? 如何从Chrome API函数向外部变量赋值? - How do I assign value to outside variable from chrome API function? React Native:一旦异步 function 返回变量,如何在 Text 元素中显示变量? - React Native: How do I display a variable in a Text element once an async function has returned it? 如何在jQuery中为返回的响应分配变量 - how do I assign a variable to a returned response in jQuery 如何更新从 function 返回的变量值 - How to update a variable value returned from a function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM