Kc's blog Kc's blog
首页
分类
标签
Timeline
收藏夹
关于
GitHub (opens new window)

kcqingfeng

前端小学生
首页
分类
标签
Timeline
收藏夹
关于
GitHub (opens new window)
  • 快应用

    • 快应用介绍
    • 快应用广告缩放
    • 华为销毁组件
    • oppo 快应用广告多次回调问题
      • 1.遇到的问题:
      • 针对问题,想解决方案:
        • 1.(pass)
        • 2.(pass)
        • 3.目前在用的
    • 猜歌需要考虑的问题
    • 快应用一些开发插件
    • 快应用不同厂商之间的差异
    • 快应用内使用eslint
  • 移动端

  • 小程序

  • 多端
  • 快应用
kc_shen
2023-03-06
目录

oppo 快应用广告多次回调问题

# 1.遇到的问题:

可能是因为在 oppo 快应用中,每个页面都是一个单独的 NativeObject 实例,当同时发起两个请求时,它们的回调函数可能会被存储在同一个 NativeObject 实例的同一个成员变量中,导致第二个请求的回调函数会覆盖第一个请求的回调函数,从而导致第二个请求的回调函数被触发时,也会触发第一个请求的回调函数,

有问题代码如下:

const ad = require("@service.ad");

const getOppoNativeAd = (adUnitId) => {
  return new Promise((resolve, reject) => {
    const nativeAd = ad.createNativeAd({
      adUnitId: adUnitId,
    });

    nativeAd.onLoad((e) => {
      e.adList[0].nativeAd = nativeAd;
      e.adList[0].isad = true;
      e.adList[0].adUnitId = adUnitId;

      // 上报曝光
      nativeAd.reportAdShow({
        adId: e.adList[0].adId,
      });

      nativeAd.offLoad();
      nativeAd.offError();
      resolve(e.adList[0]);
    });

    nativeAd.onError((err) => {
      nativeAd.offLoad();
      nativeAd.offError();
      reject(err);
    });

    nativeAd.load();
  });
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 针对问题,想解决方案:

# 1.(pass)

在多次执行 onLoad 回调时,如果要确定哪次回调属于当前请求,可以在每次请求时给 nativeAd 对象添加一个唯一标识,比如可以添加一个随机数或时间戳,然后在 onLoad 回调中判断这个标识是否与当前请求匹配

const ad = require("@service.ad")

const adRequests = {}

const getOppoNativeAd = (adUnitId) => {
  const requestId = Date.now()
  adRequests[requestId] = { adUnitId }

  return new Promise((resolve, reject) => {
    const nativeAd = ad.createNativeAd({
      adUnitId: adUnitId
    })

    nativeAd.onLoad((e) => {
      const request = adRequests[requestId]
      if (request && request.adUnitId === adUnitId) {
        delete adRequests[requestId]

        e.adList[0].nativeAd = nativeAd
        e.adList[0].isad = true
        e.adList[0].adUnitId = adUnitId

        nativeAd.offLoad()
        nativeAd.offError()
        resolve(e.adList[0])
      }
    })

    nativeAd.onError((err) => {
      const request = adRequests[requestId]
      if (request && request.adUnitId === adUnitId) {
        delete adRequests[requestId]
        nativeAd.offLoad()
        nativeAd.offError()
        reject(err)
      }
    })

    nativeAd.load()
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 2.(pass)

对每个请求都创建一个独立的 nativeAd 对象,以避免出现并发请求的问题。

同时,你可以在 nativeAd 对象上设置一个自定义属性,例如 requestId,在回调函数中判断这个属性是否和当前请求的 ID 一致,如果不一致则不处理这个回调。可以将请求 ID 存储在请求的 Promise 对象中,每个请求的 ID 都应该是唯一的。

const ad = require('@service.ad')

let requestId = 0

/**
 * 请求快应用广告
 * @param {string} adUnitId 广告位 ID
 * @return {Promise} Promise 对象,resolve 回调函数传递一个广告对象,reject 回调函数传递一个错误对象
 */
function requestNativeAd(adUnitId) {
  requestId++

  const nativeAd = ad.createNativeAd({ adUnitId })

  return new Promise((resolve, reject) => {
    const currentRequestId = requestId

    nativeAd.onLoad((event) => {
      if (currentRequestId !== requestId) {
        return
      }

      const adObj = event.adList[0]
      adObj.nativeAd = nativeAd
      adObj.isad = true
      adObj.adUnitId = adUnitId

      resolve(adObj)
    })

    nativeAd.onError((event) => {
      if (currentRequestId !== requestId) {
        return
      }

      reject(event)
    })

    nativeAd.load()
  })
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 3.目前在用的

因为造成这个问题的根源是同时请求了两个广告,这个是 oppo 快应用存在的问题,但是需求是的确需要同时请求多个广告,所以就是前面广告执行完,销毁了广告的回调监听,然后再走下一个广告的拉取,伪代码如下:

async function requestAds() {
  const adTypes = [AdType.BANNER, AdType.INTERSTITIAL, AdType.REWARDED_VIDEO];
  const ads = [];

  for (let i = 0; i < adTypes.length; i++) {
    const adType = adTypes[i];
    const ad = await requestAd(adType);
    ads.push(ad);
  }

  return ads;
}
1
2
3
4
5
6
7
8
9
10
11
12

这个是目前能想到的最好的办法,在这个示例代码中,requestAds()函数会按照顺序依次请求三种类型的广告(横幅广告、插屏广告、激励视频广告),并将每个广告的实例添加到ads数组中。requestAd()函数返回一个 Promise 对象,使用await关键字可以等待其完成后再执行下一个循环。

但是因为我的需求是多个组件之间的交互,并没有实际去操作,不知道会遇到什么问题,所以还并没有是实际的实现,目前在用的方法就是定义一个变量,每次只让一个请求进来,其他的直接走 err (做是可以做,千万别让老板知道)

这个具体的多个页面实现还没空写,直接重构的话,害怕影响其他的机型,等下个产品再来吧

编辑 (opens new window)
上次更新: 2025/04/30, 10:04:00
华为销毁组件
猜歌需要考虑的问题

← 华为销毁组件 猜歌需要考虑的问题→

最近更新
01
服务器密码管理与自动部署
04-23
02
债务问题
03-24
03
女朋友对我的不满
03-19
更多文章>
Theme by Vdoing | Copyright © 2019-2025 kc shen | MIT License 豫ICP备2024074563号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式