如何在javascript中使用承诺

如何在javascript中使用承诺,javascript,cordova,typescript,asynchronous,promise,Javascript,Cordova,Typescript,Asynchronous,Promise,我正在用Cordova为Android制作一个应用程序,带有Typescript,并与Webpack捆绑在一起。我不太了解如何在Javascript中执行异步任务。我看了一些关于回调和承诺的教程,但对我来说仍然很困惑,我无法将其适应我的代码。我不知道我的问题是源于代码本身,还是源于Typescript/Cordova/Webpack 我创建了一个函数getAllSMS,该函数返回一个大对象,执行起来需要一些时间。我知道该函数可以工作,因为如果我尝试在inspector的控制台中打印allSMS变

我正在用Cordova为Android制作一个应用程序,带有Typescript,并与Webpack捆绑在一起。我不太了解如何在Javascript中执行异步任务。我看了一些关于回调和承诺的教程,但对我来说仍然很困惑,我无法将其适应我的代码。我不知道我的问题是源于代码本身,还是源于Typescript/Cordova/Webpack

我创建了一个函数
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循环现在工作正常。