admin管理员组

文章数量:1330637

So promises is fairly new to me but I love the idea.

Previously...

I have previously used this which simply returns the data only after file is read pletely and works as intended:

function something{
     for (var i = 0; i < files.length; i++) {
         //push to the array
         promises.push(readFile(files[i]));
     }

     //use reduce to create a chain in the order of the promise array
     promises.reduce(function (cur, next) {
         return cur.then(next);
     }, Promise.resolve()).then(function () {
         //all files read and executed!
     }).catch(function (error) {
         //handle potential error
     });
}

function readFile(file) {
 return new Promise(function (resolve, reject) {
     var reader = new FileReader();
     reader.onload = function (progressEvent) {
         loadGeoJsonString(progressEvent.target.result, file.name);
         resolve();
     }

     reader.onerror = function (error) {
         reject(error);
     }

     reader.readAsText(file);
 });
}

Currently

I want to redo this by using ",then" and ".catch" to handle success and non-successes. In my current solution (Google Maps API for clarification but is irrelevant) I want to promise a function without returning a promise in the original function. This is what I have:

//create infobox object on marker
function createInfobox(lat, lng) {
var pos = new G.LatLng(lat, lng);

promiseThis(dropMarker, pos, 'drop marker')
    .then(promiseThis(getGeocodeResult, pos, 'get address'))
    .catch(reason => {alert(reason)})
    .then(promiseThis(isDeliverable, pos, 'determine deliverable status'))
    .catch(reason => {alert(reason)})
    .then(promiseThis(getStores, pos, 'find stores'))
    .catch(reason => {alert(reason)});
}

//handle promises
function promiseThis(doThis, withThis, task) {
    return new Promise(function (resolve, reject) {
        var result = doThis(withThis);
        if (result) {
            resolve(result);
        } else {
            reject('Unable to ' + task);
        }
    });
}

//drop marker on location
function dropMarker(location) {..} //return object

//get geocode results
function getGeocodeResult(latlng) {..} //return string

In the end I would like to keep the results from each promise in an array and use it later. At the moment the getGeocodeResult just returns 'Unable to get address' immediately (also as a console error, not as an alert)

What do I need to know about promises to make this work?

So promises is fairly new to me but I love the idea.

Previously...

I have previously used this which simply returns the data only after file is read pletely and works as intended:

function something{
     for (var i = 0; i < files.length; i++) {
         //push to the array
         promises.push(readFile(files[i]));
     }

     //use reduce to create a chain in the order of the promise array
     promises.reduce(function (cur, next) {
         return cur.then(next);
     }, Promise.resolve()).then(function () {
         //all files read and executed!
     }).catch(function (error) {
         //handle potential error
     });
}

function readFile(file) {
 return new Promise(function (resolve, reject) {
     var reader = new FileReader();
     reader.onload = function (progressEvent) {
         loadGeoJsonString(progressEvent.target.result, file.name);
         resolve();
     }

     reader.onerror = function (error) {
         reject(error);
     }

     reader.readAsText(file);
 });
}

Currently

I want to redo this by using ",then" and ".catch" to handle success and non-successes. In my current solution (Google Maps API for clarification but is irrelevant) I want to promise a function without returning a promise in the original function. This is what I have:

//create infobox object on marker
function createInfobox(lat, lng) {
var pos = new G.LatLng(lat, lng);

promiseThis(dropMarker, pos, 'drop marker')
    .then(promiseThis(getGeocodeResult, pos, 'get address'))
    .catch(reason => {alert(reason)})
    .then(promiseThis(isDeliverable, pos, 'determine deliverable status'))
    .catch(reason => {alert(reason)})
    .then(promiseThis(getStores, pos, 'find stores'))
    .catch(reason => {alert(reason)});
}

//handle promises
function promiseThis(doThis, withThis, task) {
    return new Promise(function (resolve, reject) {
        var result = doThis(withThis);
        if (result) {
            resolve(result);
        } else {
            reject('Unable to ' + task);
        }
    });
}

//drop marker on location
function dropMarker(location) {..} //return object

//get geocode results
function getGeocodeResult(latlng) {..} //return string

In the end I would like to keep the results from each promise in an array and use it later. At the moment the getGeocodeResult just returns 'Unable to get address' immediately (also as a console error, not as an alert)

What do I need to know about promises to make this work?

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked May 3, 2017 at 11:56 Kevin PotgieterKevin Potgieter 8083 gold badges13 silver badges26 bronze badges 5
  • What does readFile(files[i]) return? You must push functions to that array to make the reduce work – Bergi Commented May 3, 2017 at 12:10
  • You're not passing functions to then in your second snippet. Use the same approach as with catch. – Bergi Commented May 3, 2017 at 12:12
  • edited error thnx – Kevin Potgieter Commented May 3, 2017 at 12:33
  • could you please elaborate with passing to then. isnt this what is currently happening? – Kevin Potgieter Commented May 3, 2017 at 12:37
  • Your are calling functions and passing the resulting promises as arguments to then. That's not how it works - you must pass callback functions, everything else will be ignored! – Bergi Commented May 3, 2017 at 12:41
Add a ment  | 

1 Answer 1

Reset to default 5

If you your use case is to wrap function execution with a promise (to catch errors) you could do something like the code below.

You only need 1 catch function to handle errors in the entire chain. Try removing the ments and see how it behaves.

See also the promisify function which provides a nicer API in my opinion.

function promiseThis(doThis, withThis, task) {
  return new Promise((resolve, reject) => {
    const result = doThis(withThis);
    if (result) {
      resolve(result)
    } else {
      reject(`can't do task: ${task}`)
    }
  })
}

function print(name) {
  // throw Error('printing error!');
  console.log(name);
  return name;
}

function capitalizeName(name) {
  // throw Error('error capitalizing?!');
  return name.toUpperCase();
}


fetch('https://randomuser.me/api/')
  .then(response => response.json())
  .then(json => promiseThis(print, json.results[0].email))
  .then(email => promiseThis(capitalizeName, email))
  .then(email => promiseThis(print, email))
  .then(() => promiseThis(print, 'I can ignore the ining value'))
  .catch(e => console.error(e))

// You can achieve a nicer API like this
function getEmail(json) {
  return json.results[0].email
}

function promisify(f, ...args) {
  return function(resolved) {
    return new Promise((resolve, reject) => {
      resolve(f.apply(null, [...args, resolved])) 
    })
  }
}

fetch('https://randomuser.me/api/')
  .then(response => response.json())
  .then(promisify(getEmail))
  .then(promisify(print))
  .then(promisify(capitalizeName))
  .then(promisify(print))
  .then(promisify(print, 'I can ignore the ining value'))
  .catch(e => console.error(e))
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>

本文标签: javascriptAnonymous PromisesStack Overflow