【问题标题】:Promise return data cannot be assigned to class variable?承诺返回数据不能分配给类变量?
【发布时间】:2017-11-28 21:35:07
【问题描述】:

我正在尝试将承诺返回值分配给一个变量,但它没有分配。当我 console.log(this.imageref1) 时,我仍然得到空字符串。 这里的目标是获取将照片上传到 Firebase 后返回的 data.downloadURL。我需要下载的URL。将其存储在我的数据库中作为图像路径。我被困在这里,我的数据库为 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;

    });


    } 
}

【问题讨论】:

    标签: javascript angular typescript angular-promise ionic3


    【解决方案1】:
    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 ?
    • @cr-drost 指出,然后部分执行发生在 aysnc。 then 块中的代码可能会在以后执行。所以在这种情况下,this.imageref1 = tmp_url 可能会在 then 块之前执行,因此它可能不会产生您期望的结果。
    • 所以我无法让它同步?
    • 不要尝试同步调用,请根据实际意图更新问题,我们可以尝试使其以 JS 方式工作。
    • 我已经更新了这个问题。我需要获取 dataurl 以将图像路径保存在我的数据库中。所以这部分我使用 .then({ 来获取 downloadURL 很重要。我如何在没有承诺方式的情况下获取 downloadURL?
    【解决方案2】:

    所以这个值正在被设定——最终。可能您正在为它在封闭函数执行完成后发生的事实而苦苦挣扎。例如,这是一个非常简单的测试用例:

    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 个字符串记录到控制台。但是 promised 值的全部意义在于计算机正忙于计算它,它还不可用。因此,您只能在发现该值后才能实际使用它,并且您对 promise 的所有操作,包括向 .then().catch() 添加侦听器,都是异步非阻塞。当前函数完成,这些回调被放入事件循环中,只要承诺的计算完成时就会发生。

    【讨论】:

    • 谢谢你的回答哥们!。哦,这意味着 .then({ ... 中的任何内容都不会阻塞函数的流程,对吗?强制 .then({ 函数进入整个函数的流程中,我是否必须设置整个事情'imageRef.putString(this.capturedimage1, firebase.storage.StringFormat.DATA_URL).then(data=>{ that.imageref1 = data.downloadURL; });' 到一个函数?
    • @Mikethetechy:你不能从异步转到同步。运行时在说“我不会就此停下来”,而且没有办法让它变成“不,实际上你要停下来”。如果您仍在定义承诺的那个函数中,那么该回调尚未触发并且不会触发:它会在稍后安排。如果其中一部分是,您必须异步考虑整个程序,因此将任何 database-insert-whatevers 放入 .then() 回调中,以便在您知道此值时发生,而不是在您知道之前尝试执行。跨度>
    • 感谢您的回复...现在我了解了异步函数的工作原理。所以我进行数据库插入的唯一方法是在 .then() 回调中。但是,我上传图片后有一个图像列表,我需要获取下载 url 以将下载 url 存储在数据库中……它非常具有挑战性……不管我尝试哪种方式,我仍然需要获取下载 url。 .
    猜你喜欢
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 2018-08-30
    • 2020-04-30
    • 2019-09-18
    • 2012-03-09
    • 2016-09-18
    • 2015-06-27
    相关资源
    最近更新 更多