[英]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 是什么?
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.