侧边栏壁纸
博主头像
神奇的程序员

今天的努力只为未来

  • 累计撰写 170 篇文章
  • 累计创建 27 个标签
  • 累计收到 225 条评论

目 录CONTENT

文章目录

使用JS实现图文混发

神奇的程序员
2020-12-25 / 0 评论 / 3 点赞 / 707 阅读 / 2,232 字 正在检测是否收录...

前言

在我的开源项目中,很早之前实现了图文混输的功能,但是在解析消息时,解析到图片需要将其上传至服务器拿到图片地址进行特殊拼接,上传图片是异步,解析图片是同步,这就造成了文字消息已经发出去了,图片才开始上传,导致图片拼接失败。

本文就跟大家分享下我解决这个问题的实现思路以及过程,欢迎各位感兴趣的开发者阅读本文。

先跟大家展示下最终实现的效果:

实现思路

正如开头所讲,上传图片是异步,处理文字消息是同步,那么我们想办法让上传图片执行完,拿到图片返回地址后再去执行后续的处理代码,这样就可以解决我们遇到的问题了。

所以,我们现在要做的就是等异步函数执行完再执行同步函数,于是,我想到了await,我们将上传图片的函数单独提取出来,让其返回一个Promise 对象,将发送消息的函数改为 async function,这样我们就可以使用await操作符等待图片上传函数执行完成返回图片地址,将其拼接后继续执行后面的同步代码,完美解决我们遇到的问题。

接下来,我们将上述思路进行整理,如下所示:

  • 提取上传图片函数,返回一个Promise对象
  • 将发送消息的函数改为异步async
  • 解析图片时使用await执行上传图片函数
  • 消息文本拼接上传图片函数返回的文件名

await只能用于promise用于等待一个Promise 对象,要使用await当前函数必须为async的异步函数。

实现过程

实现之前先跟大家看下我的消息内容是如何描述图片信息的,如下所示,我们会用//将图片信息包裹起来。

let msgTest = `你好,我是大白/1290219.jpeg?width=658&height=658/`;

提取上传图片函数

将上传图片的函数提取出来,返回一个promise,代码如下所示:

// 上传图片
uploadImage: function(formData: FormData) {
  return new Promise((resolve, reject) => {
    // 将图片上传至服务器
    this.$api.fileManageAPI
      .upload(formData)
      .then((res: responseDataType) => {
        // 文件上传失败
        if (!_.isEqual(res.code, 0)) {
          alert(res.msg);
          reject({ msg: res.msg, code: -1 });
        }
        // 图片名
        let msgImgName = "";
        const imgSrc = `${base.lkBaseURL}/uploads/chatImg/${res.fileName}`;
        // 获取图片大小
        const img = new Image();
        let imgWidth = 0;
        let imgHeight = 0;
        // 赋值图片地址
        img.src = imgSrc;
        // 判断图片是否有缓存
        if (img.complete) {
          imgWidth = img.width;
          imgHeight = img.height;
          msgImgName = `/${res.fileName}?width:${imgWidth}&height:${imgHeight}/`;
          resolve({ msg: msgImgName, code: 0 });
        } else {
          img.onload = () => {
            imgWidth = img.width;
            imgHeight = img.height;
            msgImgName = `/${res.fileName}?width=${imgWidth}&height=${imgHeight}/`;
            resolve({ msg: msgImgName, code: 0 });
          };
        }
      });
  });
}

修改发送消息函数为异步

这一步很简单,只需要在原函数声明时添加async即可,如下所示:

// 消息发送
sendMessage: async function(event: KeyboardEvent) {
   // 其他代码省略,可移步至github查看      
}

对消息发送函数代码感兴趣的开发者请移步:sendMessage

使用await执行图片上传函数

我们在sendMessage函数内部,解析到图片时,调用上传函数上传时在其函数前面加上await,用一个变量接收它,就能拿到我们promise中resolve所返回的数据,代码如下所示。

 // 上传图片获取图片地址
const res: { code: number; msg: string } = await this.uploadImage(
   formData
);

完整代码在sendMessage中,感兴趣的开发者欢迎移步。

拼接图片信息至消息文本中

上述await会等图片上传函数执行完,将resolve返回的值复制给res,此时我门只需要从res中取值进行拼接即可,代码如下:

// 将图片地址拼接至待发送消息中
msgText += res.msg;

完整代码在sendMessage中,感兴趣的开发者欢迎移步。

实现效果

完成上述步骤后,我们的问题解决了,效果正如文章开头所看到的那样,图文混发的效果QQ是实现了的,但是微信就没实现,不晓得原因,可能正如张小龙所说的:每天都有人在教我做产品😂

文中代码地址:message-display.vue

在线体验地址:chat-system

写在最后

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊

  • 本文首发于掘金,未经许可禁止转载💌

3

评论区