我正在编写一个基于Angular2的移动应用程序,使用带有Nativescript运行时的Typescript,但我遇到了Promises的一些问题。我有一个HomeComponent,我希望能够从中调用各种蓝牙功能。这些需要人工交互(如选择设备)和等待蓝牙扫描的时间段,因此需要几秒钟才能完成。
我想将这些方法抽象为承诺,所以我已经这样做了:
bluetoothAdd() {
this.isScanning = true;
this._ble.scan().then(
// Log the fulfillment value
function (val) {
this.isScanning = false; //hide activity indicator
this.Connect(this.ble._peripheral);
})
.catch(
function (reason) {
this.isScanning = false; //hide activity indicator
console.log('Handle rejected promise (' + reason + ') here.');
});
}
var devices: Array<string>;
var _peripheral: any;
export function scan() {
return new Promise((resolve, reject) => {
bluetooth.hasCoarseLocationPermission().then(
(granted) => {
if (!granted) {
bluetooth.requestCoarseLocationPermission();
} else {
bluetooth.startScanning({
serviceUUIDs: ["133d"],
seconds: 4,
onDiscovered: (peripheral) => {
console.log("Periperhal found with UUID: " + peripheral.UUID);
}
}).then(() => {
console.log("scanning complete");
}, (err) => {
console.log("error while scanning: " + err);
});
}
});
});
}
使用调试器逐步完成我的应用程序时,在 HomeComponent 中调用bluetoothAdd()
时,BluetoothUtils中的scan()
函数按预期工作,并在一个场景中执行console.log("error while scanning: " + err);
行,说:
扫描时出现错误:蓝牙未启用
但是,HomeComponent then
承诺的catch
或this._ble.scan()
部分都没有执行?为什么是这样?你能否像我想要的那样复合承诺(即承诺中的承诺)?或任何想法如何进一步调试?
答案 0 :(得分:1)
有一些问题。
1 /您正在使用anti pattern。由于您所处理的所有内容都是承诺,因此无需在scan
中创建新承诺。
2 / a)如果你想使用反模式,你需要调用resolve
和reject
函数,即在当前情况下,新的承诺永远不会被解决也不会被拒绝,因此&#34;主要&#34; scan
中的承诺永远不会被解决或拒绝。
2 / b)更好的解决方案:只需返回已创建的承诺。如果你不回来,他们将成为独立的承诺分支,并且不会影响&#34;主要&#34;承诺scan
中的分支,即:
export function scan() {
return bluetooth.hasCoarseLocationPermission().then(
(granted) => {
if (!granted) {
return bluetooth.requestCoarseLocationPermission();
} else {
return bluetooth.startScanning({
serviceUUIDs: ["133d"],
seconds: 4,
onDiscovered: (peripheral) => {
console.log("Periperhal found with UUID: " + peripheral.UUID);
}
}).then(() => {
console.log("scanning complete");
}, (err) => {
console.log("error while scanning: " + err);
});
}
});
}
注意3添加了return
:一个位于scan
顶部,然后位于bluetooth.requestCoarseLocationPermission
和bluetooth.startScanning
之前
如果您想知道其他承诺反模式的存在,here's a great resource
答案 1 :(得分:1)
由于您使用的是打字稿,请不要再等await/async
。特别是当你有多个承诺时,它会更加清晰。
async function bluetoothAdd() {
this.isScanning = true;
try {
const val = await this._ble.scan();
this.Connect(this.ble._peripheral);
} catch (reason) {
console.log('Handle rejected promise (' + reason + ') here.');
}finally{
this.isScanning = false;
}
}
//Bluetoo.....ts
var devices: Array<string>;
var _peripheral: any;
export async function scan() {
const granted = await bluetooth.hasCoarseLocationPermission();
if(!granted){
return bluetooth.requestCoarseLocationPermission();
}else{
try {
const val = await bluetooth.startScanning({
serviceUUIDs: ["133d"],
seconds: 4,
onDiscovered: (peripheral) => {
console.log("Periperhal found with UUID: " + peripheral.UUID);
}
});
console.log("scanning complete");
return val;
} catch (err) {
// you can rethrow err here such that user `bluetoothAdd` will recieve it/
console.log("error while scanning: " + err);
}
}
}
答案 2 :(得分:0)
看起来第一个中的代码不会返回任何内容,即您没有返回承诺。我希望看到像bluetooth.startScanning(..)这样的东西。你当然可以嵌套承诺,但链接它们更具可读性。即将那时的console.log移动到与之前相同的嵌套级别。