Promise返回的数据无法赋值给类变量?

3

我试图将Promise返回值赋值给一个变量,但是它并没有被赋值。当我用console.log(this.imageref1)打印时,仍然得到空字符串。 这里的目标是获取上传照片到Firebase后返回的data.downloadURL。我需要downloadedURL来存储图像路径以在我的数据库中使用。我被卡在这里了,我的数据库获得了空的downloadURL数据。

post_news(form: NgForm){

    this.title = form.value.title;
    this.content = form.value.content;
    this.category = form.value.category;


    console.log(this.capturedimage1);


    if(this.capturedimage1 !== ''){

        //console.log('captured image is not empty');



    let storageRef = firebase.storage().ref();

    const filename = Math.floor(Date.now() / 1000);

    const imageRef = storageRef.child(`images/${filename}.jpg`);

    let uploaded_file_path = `images/${filename}.jpg`;      


    imageRef.putString(this.capturedimage1, firebase.storage.StringFormat.DATA_URL).then(data=>{

        this.imageref1 = data.downloadURL;

    });


    } 
}
2个回答

3
var that = this;
imageRef.putString(this.capturedimage1, firebase.storage.StringFormat.DATA_URL)
.then(data=>{      
    that.imageref1 = data.downloadURL;
    return Promise.resolve(data.downloadURL);
})
.then(function(url){
    //make the db call.
});

谢谢您的回答...这是否意味着我可以像这样做:var tmp_url = ''; imageRef.putString(this.capturedimage1, firebase.storage.StringFormat.DATA_URL).then(data=>{ tmp_url = data.downloadURL; }); this.imageref1 = tmp_url? - Manas
正如@cr-drost所指出的那样,then部分的执行是异步的。then块内的代码可能会在稍后的时间执行。因此,在这种情况下,this.imageref1 = tmp_url可能会在then块之前执行,因此它可能不会产生您期望的结果。 - gvmani
所以我没有办法让它同步吗? - Manas
请不要尝试将其变成同步调用,请更新问题并告诉我们实际意图,我们可以尝试使用JS的方式使其工作。 - gvmani
我已经更新了问题。我需要获取dataurl以保存图像路径到我的数据库中。因此,我使用.then({来获取downloadURL的这部分很重要。如何在没有Promise的情况下获取downloadURL? - Manas
最好和最简单的实现来捕获'this' 实例。谢谢。 - Pawan Pillai

1

所以该值最终会被设置。可能你正在为它在包含函数执行完毕后才发生这一事实而苦恼。例如,这里有一个非常简单的测试用例:

function test(x) { 
  x.a = 1;
  Promise.resolve(true).then(_ => x.b = 2); 
  console.log(x);
}

这个操作,

> test({c: 3})
{ c: 3, a: 1 }
undefined

记录一个还没有 b: 2 的对象,然后返回 undefined。当然,该参数最终会被设置:
> test(abc = {c: 3})
{ c: 3, a: 1 }
undefined
> abc
{ c: 3, a: 1, b: 2 }

为了理解真正发生的事情,您需要了解所有JS都在“事件循环”中发生。JavaScript只允许一次发生一件事情,因此当您安排其他事件发生时,JS必须遵循规则,“首先完成此函数中的所有内容,然后找到已安排好的其他事件”。有些函数调用是同步进行的,它们会阻止函数调用前进,直到它们完成。例如,[1,2,3].forEach(x => console.log('hello, ' + x))将在完成之前向控制台记录3个字符串。但承诺值的全部意义在于计算机正在忙于弄清楚它,它还没有可用。因此,只有在找到该值后才能实际使用该值,并且包括向.then()或.catch()添加侦听器在内的所有对promise的操作都是异步的或非阻塞的。当前函数完成并将这些回调放入事件循环中,以在承诺计算完成后随时发生。

谢谢你的回答,伙计!哦,这意味着在.then({ ...中的任何内容都不会阻塞函数的流程,对吧?如果要强制.then({ function在整个函数的流程中运行,我需要将整个内容'imageRef.putString(this.capturedimage1, firebase.storage.StringFormat.DATA_URL).then(data=>{ that.imageref1 = data.downloadURL; });'设置为一个函数吗? - Manas
@Mikethetechy:你不能从异步转为同步。运行时会说:“我不会在这里停下来”,而且没有办法欺骗它,“不,实际上你要在这里停下来。”如果你仍然在定义promise的函数中,那么回调还没有被触发,而且不会被触发:它稍后会被安排执行。如果程序的某个部分是异步的,你必须将整个程序都考虑成异步的,所以将任何数据库插入操作放入.then()回调中,在你知道这个值之后再执行,而不是在你不知道之前就执行。 - CR Drost
谢谢您的回复...现在我知道异步函数是怎么工作的了..所以我唯一能做数据库插入的方式就是在.then()回调里面。然而,我在上传完图像后有一个图像列表,我需要获取下载URL以将其存储在数据库中...这非常具有挑战性...无论我尝试哪种方法,我都需要获取下载URL... - Manas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接