如何在javascript中使用承诺
我正在用Cordova为Android制作一个应用程序,带有Typescript,并与Webpack捆绑在一起。我不太了解如何在Javascript中执行异步任务。我看了一些关于回调和承诺的教程,但对我来说仍然很困惑,我无法将其适应我的代码。我不知道我的问题是源于代码本身,还是源于Typescript/Cordova/Webpack 我创建了一个函数如何在javascript中使用承诺,javascript,cordova,typescript,asynchronous,promise,Javascript,Cordova,Typescript,Asynchronous,Promise,我正在用Cordova为Android制作一个应用程序,带有Typescript,并与Webpack捆绑在一起。我不太了解如何在Javascript中执行异步任务。我看了一些关于回调和承诺的教程,但对我来说仍然很困惑,我无法将其适应我的代码。我不知道我的问题是源于代码本身,还是源于Typescript/Cordova/Webpack 我创建了一个函数getAllSMS,该函数返回一个大对象,执行起来需要一些时间。我知道该函数可以工作,因为如果我尝试在inspector的控制台中打印allSMS变
getAllSMS
,该函数返回一个大对象,执行起来需要一些时间。我知道该函数可以工作,因为如果我尝试在inspector的控制台中打印allSMS
变量,它首先是空的,然后像1秒一样填充。(我认为检查员的行为很奇怪,但确实如此)
我看到我可以通过承诺来完成异步任务,但我在理解它的工作原理时遇到了一些问题。我看过一些教程,但我仍然不明白如何将其应用到我的代码中
谢谢
[编辑]:下面是我的getAllSMS函数转换为承诺:
public getAllSMS() {
return new Promise(//return a promise
(resolve,reject)=>{
if (SMS) {
SMS.listSMS(this.filters, function (data) {
resolve(data);//added this, resolve promise
}, function (err) {
console.log('error list sms: ' + err);
reject(err);//added this reject promise
});
}else{
resolve([]);//added this, resolving to empty array?
}
}
).then(
data=>{
let contacts = {};
for (let key in data) {
if ((data[key].address).length > 7 && (data[key].address).match("[0-9]+")) {
let date = SMSManager.convertUnixDate(data[key].date); // on converti le format de date de listSMS
if (contacts.hasOwnProperty(data[key].address)) {
Object.defineProperty(contacts[data[key].address], data[key]._id, {
value: {
"body": data[key].body,
"date": date
}
});
} else {
let myid = String(data[key]._id);
Object.defineProperty(contacts, data[key].address, {
value: {
"000": {
"body": data[key].body,
"date": date
}
}
});
}
}
}
return contacts;
}
);
}
编辑2:我这样调用我的函数,但是我的for in循环仍然没有执行,尽管我的变量似乎加载正确
sms.getAllSMS().then( allSMS => {
console.log('allSMS');
console.log(allSMS);
console.log('then is readed'); // this is readed
for (let key in allSMS) {
console.log(allSMS[key]); // this is not executed
}
}).catch(
error => console.warn("something is wrong")
);
这里是控制台的屏幕截图(“控制台中的对象”是allSMS)。在“Object”旁边有一个小“i”,上面写着:“下面的值现在刚刚被评估过”。
我怀疑sms.getAllSMS会返回一个承诺,因此您可以尝试以下操作:
sms.getAllSMS()
.then(
allSMS => {
for (let key in allSMS) {
console.log(allSMS[key]);
}
}
)
.catch(
error=>console.warn("something went wrong, error is:",error)
)
您的getAllSMS不会返回任何内容,请确保它返回承诺:
public getAllSMS(): object {
return new Promise(//return a promise
(resolve,reject)=>{
if (SMS) {
SMS.listSMS(this.filters, function (data) {
resolve(data);//added this, resolve promise
}, function (err) {
console.log('error list sms: ' + err);
reject(err);//added this reject promise
});
}else{
resolve([]);//added this, resolving to empty array?
}
}
).then(
data=>{
let contacts = {};
data.forEach(
item=>{
if ((item.address).length > 7 && (item.address).match("[0-9]+")) {
let date = SMSManager.convertUnixDate(item.date); // on converti le format de date de listSMS
if (contacts.hasOwnProperty(item.address)) {
Object.defineProperty(contacts[item.address], item._id, {
value: {
"body": item.body,
"date": date
}
});
} else {
Object.defineProperty(contacts, item.address, {
value: {
"000": {
"body": item.body,
"date": date
}
}
});
}
};
}
);
return contacts;
}
);
}
您现在通过使用承诺修复了异步问题,看起来不错
for
循环未枚举属性的问题在于(默认情况下)创建了不可枚举的属性。改为使用简单的赋值:
let contacts = {};
for (const key in data) {
const address = data[key].address;
if (address.length > 7 && address.match("[0-9]+")) {
const date = SMSManager.convertUnixDate(data[key].date); // on converti le format de date de listSMS
const myid = String(data[key]._id);
if (address in contacts) {
contacts[address][myid] = {
"body": data[key].body,
"date": date
};
} else {
contacts[address] = {
"000": {
"body": data[key].body,
"date": date
}
}
}
}
}
return contacts;
您需要向我们显示
getAllSMS
中的代码。其中的某些东西需要时间,而这正是需要用承诺来包装的东西。如果let allSMS=sms.getAllSMS()
您拥有的函数不起作用,在调用周围作出一些承诺不会改变函数不起作用的任何情况。请参阅,它有2个参数。另请看Promise.prototype.catch()
resolve()
通常不将函数作为参数,您可能希望将那里的代码放入then()
。只看一些例子。在函数sms.getAllSMS()中返回新的承诺,并在then()中编写函数getAllSMS更新答案,您的getAllSMS将返回一个对象,该对象将来可能会或可能不会变异为有价值的东西。相反,您应该返回一个承诺,以便知道数据何时可用以及是否可用(无错误)。@Bergi是的,我误解了如何使用承诺,这就是为什么我试图“围绕”该函数。但是我知道这个函数是可以工作的,因为如果我对变量contact
执行console.log,该变量应该在函数内部返回,那么它就可以工作了。如果我尝试在then函数中使用console.log,则如下所示:sms.getAllSMS().then(allSMS=>{console.log(allSMS);}
,它也在工作。但是for-in-loop-after仍然没有执行。谢谢!但是它仍然没有工作…我已经编辑了我的帖子。@neiya你的更新显示了一个getAllSMS
,它没有返回任何内容,我的答案中的getAllSMS
返回了一个承诺。另外dosnt-work
使用sms.getAllSM>也不是很有帮助然后(…
使用sms.getAllSMS
在您的问题中应该会得到一个sms.getAllSMS不是一个函数
错误。在我的更新中getAllSMS()是否返回承诺否?我在函数的开头添加了一个return new promise
,正如您建议我做的那样。我在控制台中没有任何错误,for-in循环中的代码只是没有执行,因为我认为当时没有加载对象。我认为我的代码中仍然有错误,但我找不到位置。我添加了一些“我的帖子的屏幕截图向您展示了控制台。@neiya是的,我现在看到了更新。您似乎想解析联系人,但正在异步对其进行变异。我更新了答案,先获取数据,然后根据数据对联系人进行变异。我尝试了您的代码,并对其进行了一些修改(我在主帖子中对其进行了更新)因为我不能对对象执行forEach
。但是当我执行sms.getAllSMS().then()时
对象内部的for-in循环仍然没有加载。我想在该对象上执行除for-in循环之外的其他一些不同的操作,这就是为什么不想将该代码放入getAllSMS
函数中。哦,我明白了,我永远也不会明白这一点。谢谢,for-in循环现在工作正常。