Cache home location and weather across page navigation
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
const { secure } = require("./api");
|
||||
|
||||
const STORAGE_KEY = "pet_environment_v1";
|
||||
let value;
|
||||
let attempted = false;
|
||||
let pending;
|
||||
let failure;
|
||||
|
||||
function cached() {
|
||||
if (value === undefined) {
|
||||
const saved = wx.getStorageSync(STORAGE_KEY);
|
||||
value =
|
||||
saved &&
|
||||
typeof saved.locationName === "string" &&
|
||||
typeof saved.weatherLabel === "string" &&
|
||||
Number.isFinite(saved.updatedAt)
|
||||
? saved
|
||||
: null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
async function fetchEnvironment(tapped) {
|
||||
const settings = await new Promise((resolve, reject) =>
|
||||
wx.getSetting({ success: resolve, fail: reject }),
|
||||
);
|
||||
if (settings.authSetting["scope.userLocation"] === false) {
|
||||
if (!tapped) throw new Error("location-denied");
|
||||
const enabled = await new Promise((resolve, reject) =>
|
||||
wx.openSetting({ success: resolve, fail: reject }),
|
||||
);
|
||||
if (!enabled.authSetting["scope.userLocation"])
|
||||
throw new Error("location-denied");
|
||||
}
|
||||
const point = await new Promise((resolve, reject) =>
|
||||
wx.getLocation({ type: "gcj02", success: resolve, fail: reject }),
|
||||
);
|
||||
const result = await secure("/environment", "GET", {
|
||||
latitude: point.latitude,
|
||||
longitude: point.longitude,
|
||||
});
|
||||
if (!result || !result.location_name)
|
||||
throw new Error("位置和天气获取失败,请重试");
|
||||
const previous = cached();
|
||||
value = {
|
||||
locationName: result.location_name,
|
||||
weatherLabel: result.weather
|
||||
? `${result.weather.description} ${result.weather.temperature}°C`
|
||||
: previous && previous.locationName === result.location_name
|
||||
? previous.weatherLabel
|
||||
: "天气暂不可用",
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
// Store display data only; precise coordinates are not persisted here.
|
||||
try {
|
||||
wx.setStorageSync(STORAGE_KEY, value);
|
||||
} catch (_) {}
|
||||
return value;
|
||||
}
|
||||
|
||||
function refresh(tapped = false) {
|
||||
if (pending) return pending;
|
||||
// Module lifetime follows the app, including recreated pages and warm resumes.
|
||||
// Failed automatic attempts also wait for a tap or the next cold start.
|
||||
if (attempted && !tapped)
|
||||
return failure ? Promise.reject(failure) : Promise.resolve(cached());
|
||||
attempted = true;
|
||||
pending = fetchEnvironment(tapped)
|
||||
.then(
|
||||
(result) => {
|
||||
failure = null;
|
||||
return result;
|
||||
},
|
||||
(error) => {
|
||||
failure = error;
|
||||
throw error;
|
||||
},
|
||||
)
|
||||
.finally(() => {
|
||||
pending = null;
|
||||
});
|
||||
return pending;
|
||||
}
|
||||
|
||||
module.exports = { cached, refresh };
|
||||
Reference in New Issue
Block a user