环境
最近在写小程序。为了提升效率, 后端采用graphQL。
前端的graphQL库, 打算用Apollo。
小程序框架, 采用的是wepy
问题描述
按照Apollo的说明, 写了一个简单的方法,用来请求gql服务。
然而, 在小程序上跑的时候, 却报错了, 说是没有fetch.
问题分析
原来, 微信小程序在某一次升级中, 移除了全局的fetch。导致createHttpLink里的报错。
此时, 可以想到, 有两种可能的方案
1. 自己写一个fetch, 并且放到全局。
2. 自己写一个fetch, 并且在createHttpLink被调用的时候, 传递一个fetch。
解决过程
第一个方案没有成功, 因为小程序貌似和浏览器不一样, 没办法把一个变量直接放到全局。(也可能是因为我才用的是wepy框架?)
第二个方案, 修改调用createHttpLink的参数。 问题是, createHttpLink不是我调用的, 而是在new ApolloClient()时, Apollo库代码调用的。
当然可以去修改apollo的源代码, 但是如果库的代码更新了怎么办, 会遗留下来麻烦。(也可以发pull request, 把修改并入主库)
于是我采用了另一个方法: 用高阶函数包装一下createHttpLink方法, 把fetch参数注入实参里。
用法:
apolloFetchFix.js内容:
import wepy from 'wepy'
const fetch = async (url, options) => {
console.log('will fetch', url, JSON.parse(options.body))
const res = await wepy.request({
url,
method: 'POST',
data: JSON.parse(options.body)
})
res.text = () => Promise.resolve(JSON.stringify(res.data))
return res
}
function injectFetcher(func) {
return function(linkOptions) {
return func.call(this, {
...linkOptions,
fetch: fetch
})
}
}
import * as ApolloLinkHttp from 'apollo-link-http'
ApolloLinkHttp.HttpLink = injectFetcher(ApolloLinkHttp.HttpLink)
这样之后, Apollo就愉快的在wepy上跑起来了。
说明
这里的fetch只是简单的实现了一下, 以跑通我的项目为度。 离通用的polyfill还有一段距离。如果你正好也需要在小程序里用fetch, 可以留言给我。 人多的话, 我们可以一起实现一个开源的, 微信小程序上的fetch。