收藏
回答

wx.cloud.uploadFile何时返回调用成功?遇到一个很奇怪的问题

首先,上代码片段

release(e){
    var imageUrl = [];
    var temp = [];
    for (var i = 0; i < this.data.filepath.length; i++) {
      wx.cloud.uploadFile({
        cloudPath: this.data.cloudpath[i],  // 上传至云端的路径
        filePath: this.data.filepath[i],   // 小程序临时文件路径
        success: res => {
          imageUrl = imageUrl.concat(res.fileID)
          temp = res.fileID
          console.log('imageUrl', imageUrl)
        }
      })
    }
    console.log('imageUrl aaaa', imageUrl)
    console.log('temp bbbb', temp)
 
    db.collection('emall').add({
      data: {
        title: this.data.location + '出租',
        price: this.data.price + '/月',
        image: imageUrl,
        inDate: this.data.date,
        pictureCnt: i,
      },
      success: res2 => {
        console.log('文件上传成功', res2)
        wx.showToast({
          title: '新增成功',
        })
      },
      fail: err => {
        console.error('error', err)
      }
    })
},

背景介绍:

  1. 我有一个商品信息需要上传到数据库,这个商品有多张图片来描述;

  2. 在上面的release接口中,有一个for循环,实现上传多张图片到腾讯云,把上传成功的fileid用一个数组记录下来

  3. 所有图片上传成功后,将这些腾讯云的图片路径和商品信息保存在一个数据库记录中

遇到的问题

实际调试时,发现程序执行到wx.cloud.uploadFile时,并没有等待这个数据是否上传成功,而是继续向下执行了,因此会发现先打印了

imageUrl aaaa
temp bbbb

然后会接着打印,以及真正的云端路劲地址

imageUrl

疑惑的地方

  1. 在函数release中调用wx.cloud.uploadFile的时候,它并不知道什么时候上传成功,就会直接跳转到后面的函数执行,那有什么办法能够确认wx.cloud.uploadFile函数执行成功后再继续执行release函数后面的语句吗?

  2. 因为我是嵌入式C语言出生,小程序以及js语言完全属于自学,这样的用法感觉好奇怪,一个函数里面像是发生了线程调度,被打断后,继续执行这个函数后面的操作,这是什么逻辑操作?还是很多前端部分的语言都是这个德行?按照C语言的执行流程,这个时候release函数就应该block在这边,等待wx.cloud.uploadFile执行完成之后,再继续执行;或者你也可以引发一次线程调度,执行其他的部分,但是release函数肯定是被block住的。

  3. 等图片上传成功后,又返回到wx.cloud.uploadFile的success中继续执行,可是给我感觉在图片上传成功之前,release整个函数都应该执行结束了,然后微信小程序还会继续自行跳转到这个函数中来执行,这个又是什么神操作?那么release这个函数的生命周期究竟是多少?

  4. 难怪之前在网上看到有人用了递归的方法来做wx.cloud.uploadFile,当时还没完全理解别人这样做的意义何在,今天调试下来感觉应该就是现在反馈的问题带来的处理,可是循环比递归理解起来简单多了呀

最后一次编辑于  2019-08-19
回答关注问题邀请回答
收藏

6 个回答

  • 2019-08-19

    经过调试之后,现在想到了一个解决策略,等待多张图片都存放到腾讯云之后,再将这些图片的云存储路径存放到的数据库中,代码如下

    release(e){
        //console.log('I am here', e)
        var imageUrl = [];
        var temp = [];
        var uploadSuccessCnt = 0;
        for (var i = 0; i < this.data.filepath.length; i++) {
          wx.cloud.uploadFile({
            cloudPath: this.data.cloudpath[i],  // 上传至云端的路径
            filePath: this.data.filepath[i],   // 小程序临时文件路径
            success: res => {
              //console.log('I am here', res)
              imageUrl = imageUrl.concat(res.fileID)
              temp = res.fileID
              //console.log('imageUrl', imageUrl)
              uploadSuccessCnt++;
              //console.log('uploadSuccessCnt', uploadSuccessCnt)
              if (uploadSuccessCnt == i){
                db.collection('emall').add({
                  data: {
                    title: this.data.location + '出租',
                    price: this.data.price + '/月',
                    image: imageUrl,
                    inDate: this.data.date,
                    pictureCnt: i,
                  },
                  success: res2 => {
                    console.log('文件上传成功', res2)
                    wx.showToast({
                      title: '新增成功',
                    })
                  },
                  fail: err => {
                    console.error('error', err)
                  }
                })
              }
            }
          })
        }
    },

    但是帖子中的几个疑惑的地方还是不是很明白

    2019-08-19
    有用 2
    回复 1
    • MAYA
      MAYA
      2020-05-16
      楼主,你用了这个uploadSuccessCnt之后,真机调试时出现cloud.uploadFile调用失败了吗,我在开发者工具中调试没有问题,但是真机调试预览调试都失败了
      2020-05-16
      回复
  • 军0000
    军0000
    2021-12-13

    虽然不是和理解,但照这个方法解决了问题,很感谢

    2021-12-13
    有用
    回复
  • 李跃龙13032617513
    李跃龙13032617513
    2020-04-30

    可算tm解决了。用了你 计数的方法。uploadSuccessCnt++; 太感谢你了,就这一个问题。我坐这儿两天了,头都要炸了。我真看不懂那些 递归的什么鬼。 异步那个好像很有道理,但本人脑子不好使,还是你这个实惠方便。

    2020-04-30
    有用
    回复
  • 2019-10-15

    我也研究过,wx.cloud.uploadFile,可以读取外部的变量,并且在函数内部继续变化,但最终的值是不能传个函数外部的。

    /**上传照片到云端 */

    confirmUpload: function() {

    var temp = this.data.tempFilePaths

    var length = temp.length

    var upLoadCount1 = 0


    for (let i = 0; i < length; i++) {

    // 上传图片

    const filePath = this.data.tempFilePaths[i]

    const cloudPath = 'my' + i.toString() + filePath.match(/\.[^.]+?$/)



    //云端调用,引用的外部变量的值不能回传给外部

    wx.cloud.uploadFile({

    cloudPath,

    filePath,

    success: res => {

    console.log('[上传文件] 成功:i=', i, res)

    upLoadCount1++

    //比较计数器和准备上传的照片数,

    if (upLoadCount1==length){


    wx.showToast({

    title: upLoadCount1.toString() + '个照片传成功!'

    })

    }




    },

    fail: e => {

    console.error('[上传文件] 失败:', e)

    wx.showToast({

    icon: 'none',

    title: '上传失败',

    })

    },

    complete: () => {


    }

    })

    }


    },


    2019-10-15
    有用
    回复
  • 老张
    老张
    2019-08-20

    异步的原因,改成同步就没毛病了。

    2019-08-20
    有用
    回复 1
    • 2019-08-20
      你好,请问怎么改成同步的?因为刚开始接触,经验还不足
      2019-08-20
      回复
  • 未命名科技
    未命名科技
    2019-08-19

    理解一下异步。上传是异步操作,这一部分代码执行后异步上传还在进行中,但是代码会往下面执行。success 回调被调用时后面代码都已经执行完了。

    2019-08-19
    有用
    回复 1
    • 2019-08-20
      首先感谢您的答复!可是按照异步来理解还是感觉有点牵强,从表现来看确实是异步操作的表现。wx.cloud.uploadFile像是创建了一个异步线程,release函数中创建了这个线程,难道这个线程的实现部分也放在了release函数中,同时变量i的生存期不应该是在release中吗,为什么在wx.cloud.uploadFile也可以使用这个变量,奇怪
      2019-08-20
      回复
登录 后发表内容
问题标签