Javascript 如何将异步函数返回的值分配给变量
我是JavaScript新手,一直在努力阅读大量关于为什么这不起作用的文章。这是我的密码。我在这里也读了很多关于堆栈溢出的文章,但仍然感觉很密集 此外,如果我的标题没有意义,请建议编辑Javascript 如何将异步函数返回的值分配给变量,javascript,asynchronous,Javascript,Asynchronous,我是JavaScript新手,一直在努力阅读大量关于为什么这不起作用的文章。这是我的密码。我在这里也读了很多关于堆栈溢出的文章,但仍然感觉很密集 此外,如果我的标题没有意义,请建议编辑 listRef.listAll() .then(response => { let files = [] response.items.forEach(item => {
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
}
}
该代码“有效”,因为它将响应记录到控制台,但text变量是一个挂起的promise对象
我知道异步函数会返回一个承诺,所以当我调用getText时,我需要使用它。然后-我正在努力解决的问题是,我多次重构了这段代码:
如何将doc.data().text的值分配给稍后使用的变量?换句话说,var text如何可以是实际字符串而不是挂起的承诺对象
如果我替换了javascript,也可以在异步函数中学习javascript
if (doc.exists){
return doc.data().text
}
与
我在console.log中得到了相同的结果-这是预期的吗?return仅仅是处理者解决承诺的简写吗
我还将这段代码重构为非异步的,并且得到了相同的结果,其中我的var文本基本上是一个挂起的承诺,而不是解析的数据
谢谢你的帮助-还有任何文章来帮助我解释这将是伟大的!我一直在学习udemy的课程,但现在对此有点困惑实际上,您正在为变量文本指定完整的承诺 替换
var text = getText(item.name).then(res=>console.log(res))
借
或
实际上,您正在为变量text 替换
var text = getText(item.name).then(res=>console.log(res))
借
或
当然,
文本
将成为一个承诺
Promise.then()
始终返回一个Promise
考虑以下代码:
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);
您希望输出是什么
- 1、2、4和7将始终按顺序排列,因为它们是同步执行的
- 3永远不会在1和2之前打印。同样,5和6在1、2和4之前也不会打印
- 但是,3、5和6可以按任何顺序打印,因为异步函数不保证创建后的执行顺序
- 而且,4可以在3之前打印。同样,7可以在5和6之前打印
因此,您需要将所有需要设置
text
值的代码放入Promise
的回调块中,如下所示:
getText(item.name).then((text) => {
// put everything that uses text here
});
这当然会导致臭名昭著的“回调地狱”,在异步回调的层中有层。有关详细信息和缓解技术,请参阅
async/await
只是做同样事情的较新方法之一:MDN在这里有一篇优秀的文章:当然text
将是一个承诺Promise.then()
始终返回一个Promise
考虑以下代码:
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);
您希望输出是什么
- 1、2、4和7将始终按顺序排列,因为它们是同步执行的
- 3永远不会在1和2之前打印。同样,5和6在1、2和4之前也不会打印
- 但是,3、5和6可以按任何顺序打印,因为异步函数不保证创建后的执行顺序
- 而且,4可以在3之前打印。同样,7可以在5和6之前打印
基本上,可以将异步函数视为独立运行的并行任务(虽然不是真正的;单线程JS只模拟这种行为)。它可以随时返回(完成/拒绝)。出于这个原因,您不能简单地使用同步代码将异步函数的返回值分配给变量-在同步执行时,该值不保证(可能也不保证)可用
因此,您需要将所有需要设置text
值的代码放入Promise
的回调块中,如下所示:
getText(item.name).then((text) => {
// put everything that uses text here
});
这当然会导致臭名昭著的“回调地狱”,在异步回调的层中有层。有关详细信息和缓解技术,请参阅
async/await
只是做同样事情的较新方法之一:MDN在这里有一篇很好的文章:好的,我和同事一起工作,找到了一个解决方案-它与本文相关
我在for-each循环中使用异步函数
重构代码在这里
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)
也要感谢@cyqsimon和@Nav Kumar V好的,我和工作中的某个人一起工作,找到了一个解决方案——这与本文有关
我在for-each循环中使用异步函数
重构代码在这里
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)
还要感谢@cyqsimon和@Nav Kumar V嘿,非常感谢您的回复!我知道我只能在一个异步函数中使用wait-所以我不确定这是否对我有效也很抱歉我想我看到了我的问题,但仍然不确定为什么我用完整的代码编辑了我的原始帖子-所以当我调用getText时,它在另一个函数中。然后方法嘿,非常感谢你的回复!我知道我只能在异步函数的内部使用wait-所以我不确定这是否对我有效也很抱歉我想我看到了我的问题,但仍然不确定为什么我用完整的代码编辑了我的原始帖子-所以当我调用getText时,它在另一个内部。然后方法谢谢你解释更多,我确实编辑了我的主要问题,以包括我调用异步函数的全部范围,我认为这可能是我的问题的一部分,如果我在外部调用它。然后在listRef上,一切都正常