How to use promises in javascript

瘦欲@ 提交于 2020-01-30 08:11:08

问题


I am making an app for Android in Cordova, with Typescript, and I bundle with Webpack. I don't understand very well how to do asynchronous tasks in Javascript. I saw several tutorials on callbacks and promises, but it's still very confused for me and I don't manage to adapt it to my code. I don't know if my problem comes from my code itself, or from Typescript/Cordova/Webpack.

I created a function getAllSMS that return a big object, and takes some time to execute. I know the function works because if I try to print the allSMS variable in the inspector's console, it's empty at first and then filled in like 1 second. (I think that behavior of the inspector is quite strange, but it really does that).

I saw I can do asynchronous tasks with promises, but I have some problems to understand how it works. I have seen several tutorials but I still don't understand how to apply it to my code.

Thanks

[EDIT] : Here's my getAllSMS function converted to a promise :

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;
        }
    );
}

EDIT 2 : I call my function like that, but my for in loop is still not executed , although my variable seems correctly loaded.

    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")
    );

Here's a screenshot of the console ('Object' in the console is allSMS). Next to "Object" there's a little "i" that says : "Value below was just evaluated right now".


回答1:


I suspect sms.getAllSMS returns a promise so you can try the following:

sms.getAllSMS()
.then(
  allSMS => {
    for (let key in allSMS) {
      console.log(allSMS[key]);
    }
  }
)
.catch(
  error=>console.warn("something went wrong, error is:",error)
)

Your getAllSMS does not return anything, make sure it returns a promise:

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;
    }
  );
}



回答2:


You fixed the asynchrony problem now by using promises, that looks fine.

The problem with the for loop not enumerating your properties is that Object.defineProperty does (by default) create non-enumerable properties. Use a simple assignment instead:

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;


来源:https://stackoverflow.com/questions/49896138/how-to-use-promises-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!