目录

通用规则

接口方法有同步、异步、回调、异步回调四种类型,不同类型的接口方法,提供的能力也不相同。

同步接口

同步接口会直接返回调用结果,结果可以是任意类型,参见相关的接口文档。使用示例如下:

console.log(JSON.stringify(app.getInfo()))

异步接口

异步接口不会立即返回调用结果,开发者需要提供合适的回调函数,异步接口会在任务结束时调用相应的回调函数。目前提供了两种异步接口的调用方式:异步接口回调方式和Promise的方式,其中Promise的方式是在1010+规范以后开始支持。异步接口支持的回调函数如下表所示。

回调函数

参数

类型

说明

success

data

any

调用结果,可以是任意类型,参见接口使用文档。

fail

data

any

在调用失败时回调。

错误信息,一般是描述错误信息的字符串,也可以是其他类型,参见接口使用文档。

code

number

在调用失败时回调。

错误代码,如果文档未特别说明,会返回200。如果返回其他错误代码,需要在文档中列举说明。

cancel

data

any

在用户取消时回调。部分需要用户交互的接口调用中可能提供此回调支持。调用结果,一般无内容,参见接口使用文档。

complete

无

无

在调用完成时回调。

success、fail和cancel三个回调函数是互斥的,每次接口调用都会且仅会调用这三个回调函数中的一个,之后会再调用一次complete回调。

使用示例如下:

prompt.showContextMenu({
  itemList: ['item1', 'item2'],
  itemColor: '#ff33ff',
  success: function(data) {
    console.log("handling callback");
  },
  fail: function(data, code) {
    console.log("handling fail, code=" + code);
  },
  cancel: function(data) {
    console.log("handling cancel");
  },
  complete: function() {
    console.log("handling complete");
  },
})

[h2]Promise方式(1010+)

异步接口支持返回Promise的方式,方便开发者实现以async的方式编写代码,增强代码的可读性与控制。

不适用于卡片场景。

在接口调用时如果在参数中没有传入任何回调函数(success、fail、cancel、 complete),那么在接口调用时会返回一个Promise对象,开发者可以通过Promise对象来处理接口的调用结果。

下面以调用system.device接口为例:

async function testAsync(){
    try{
    let res = await device.getDeviceId()
        console.debug("get device id " + JSON.stringify(res.data)) 
    }catch(err){
        console.log("get device id error " + e.code )
    }
}

device.getDeviceId()接口的返回值是一个Promise对象,开发者可以通过await的方式获取接口的调用成功结果,在catch里面获取调用失败的结果。对于接口调用成功是返回一个对象res = {data} ,开发者可以通过res.data获取接口实际返回的结果,通过res.code获取失败的返回code。

对于每个接口如果都捕获catch,将导致代码臃肿,开发者可以通过封装一个catching函数统一处理:

function catching(promise){
         return promise.then(res =>res).catch(err =>err)
}
var ret = await catching(device.getDeviceId())

如果接口调用时传入了任意一个回调函数,那么接口仍将按照之前异步回调的方式返回结果,而不会返回Promise。

在1040及以上版本的快应用引擎中,已完全支持async await,所以只有manifest.json的minPlatformVersion配置了1040以下版本,使用await才需要执行如下操作。

在app.ux中注入@babel/runtime/regenerator,示例代码如下:

//minPlatformVersion配置1040以下版本才需要配置,从1040版本开始无需配置
const injectRef = Object.getPrototypeOf(global) || global;
// injection regeneratorRuntime
injectRef.regeneratorRuntime = require('@babel/runtime/regenerator');

回调

同异步接口一样,回调接口也不会立即返回调用结果,开发者需要提供合适的回调函数,回调接口会调用相应的回调函数。不同的是,回调接口可能会多次调用回调函数返回结果。回调接口支持的回调函数如下表所示。

回调函数

参数

类型

说明

callback

data

any

在每次获得结果时回调,可能会回调多次。调用结果,可以是任意类型,参见接口使用文档。

fail

data

any

调用失败时回调。一旦调用此回调,callback调用不会再被调用,接口调用结束。

调用结果一般是描述错误信息的字符串,也可以是其他类型,参见接口使用文档。

以地理位置接口(system.geolocation)为例:

geolocation.subscribe({
  callback:function(ret){console.log("handling callback");},
  fail: function(data, code) {
    console.log("handling fail, code=" + code);
  }
})

异步回调

同异步接口一样,异步回调接口不会立即返回调用结果,开发者需要提供合适的回调函数,接口在执行完成时会调用回调函数返回结果。

同异步接口不同的是,这类接口仅接受一个callback回调,调用成功与否需要在callback回调中判断返回的结果来确定。callback仅会被回调一次。

异步回调接口支持的回调函数如下表所示。

回调函数

参数

类型

说明

callback

data

any

在获得结果时回调,会且仅会回调一次。调用结果,可以是任意类型,参见接口使用文档。

alipay.pay({
  orderInfo:"order1",
  callback:function(ret){console.log("handling callback");}
})

正确实现回调函数

除同步接口外,异步接口、回调接口、异步回调接口都不会在调用后立即返回结果,而是一段时间后执行回调函数并携带返回结果作为参数。同时,执行接口调用所处的页面与最终执行回调函数的页面可能是两个不同的页面。

假设执行接口调用的页面为A,那么最后执行回调函数时,有可能处于以下三种状态中的一种:

  1. A页面仍然在显示中;
  2. A页面被切换到后台,当前显示的是页面B;
  3. A页面已经被销毁。

回调函数需要判断页面的状态,并根据状态做出正确的处理。页面拥有$valid和$visible属性,为布尔值,以方便判断页面状态:

// 页面是否有效(没有被销毁)
this.$valid
// 页面是否处于后台
this.$visible

举个例子:有个页面需要展示用户当前地理位置的商户列表,需要先调用geolocation.getLocation()接口获取当前的位置信息,然后调用fetch.fetch()接口获取商户列表。在实现geolocation.getLocation()的回调函数时,就需要判断当前页面的状态进行不同的操作:

示例代码如下。

geolocation.getLocation({
  success:function(data){
    if (this.$valid && this.$visible) {
      // 页面处于当前显示中
    }
    else if (this.$valid && !this.$visible) {
      // 页面处于后台
    }
    else {
      // 页面处于被销毁
    }
  }.bind(this),
  fail: function(data, code) {
    console.log("handling fail, code=" + code);
  }
})

需要特别注意的是,回调接口的回调函数会被多次调用。如果在页面切换到后台或者被销毁后,回调函数仍然被多次回调的话,既会影响应用的响应速度,也会造成内存泄露。因此,强烈建议使用下面任一种方法取消回调接口调用:

  1. 在页面的onHide函数或onDestroy函数中取消回调接口调用。
  2. 在回调函数中判断当前页面的状态,发现页面被切换到后台或销毁后取消回调接口调用。

推荐使用第1种方法,因为它能更及时的取消回调,最好的避免额外消耗。

举个例子,有个页面调用geolocation.subscribe记录用户的运动轨迹。

使用第1种方法取消回调接口调用的逻辑如下:

示例代码如下:

export default {
  onDestroy () {
    geolocation.unsubscribe()
  },
  record() {
    geolocation.getLocation({
      success:function(data){
        if (this.$valid && this.$visible) {
          // 页面处于当前显示中,记录轨迹
        }
        else if (this.$valid && !this.$visible) {
          // 页面处于后台,记录轨迹
        }
        else {
          // 页面处于被销毁,不做处理
        }
      }.bind(this),
      fail: function(data, code) {
        console.log("handling fail, code=" + code);
      }
    })
  }
}

使用第2种方法取消回调接口调用的逻辑如下:

示例代码如下:

geolocation.getLocation({
  success:function(data){
    if (this.$valid && this.$visible) {
      // 页面处于当前显示中,记录轨迹
    }
    else if (this.$valid && !this.$visible) {
      // 页面处于后台,记录轨迹
    }
    else {
      // 页面处于被销毁
      geolocation.unsubscribe()
    }
  }.bind(this),
  fail: function(data, code) {
    console.log("handling fail, code=" + code);
  }
})

在应用生命周期回调中可以调用接口方法,这种调用接口的方式与页面无关,只要应用仍然在运行中,接口调用都有效。即使是这种情况,也强烈建议在确定不需要回调接口的时候,主动取消回调接口的调用。

常见错误代码

代码

含义

200

一般性错误。

201

用户拒绝。

202

参数非法。

203

服务不可用。

204

请求超时。

相关链接

[h2]案例