JavaScript中的承诺有什么意义?

时间:2017-05-15 15:01:37

标签: javascript asynchronous promise es6-promise

承诺是

  

(...)现在或将来可用或永不可用的值(来源:MDN)

所以我想说我有一个想要处理图片的应用程序。例如,加载图片在算法在后台(或其他类型的延迟)中使用它之后。现在我想检查一下,如果图片在将来中可用,则使用promise,而不是回调。

要检查,如果图像可用,我可以使用以下代码:

function loadImage(url) {
  return new Promise((resolve, reject) => {
    let image = new Image()

    image.onload = function() {
      resolve(image)
    }

    image.onerror = function() {
      let message =
        'Could not load image at ' + url
      reject(new Error(msg))
    }

    image.src = url
  })
}

属于此的承诺看起来像这样:

Promise.all([
  loadImage('images/pic1.jpg'),
  loadImage('images/pic2.jpg')
]).then((images) => {
  images.forEach(img => addImg(img.src))
}).catch((error) => {
  // handle error 
})

这根本不会对我有所帮助,因为如果图片在现在中可用,而不是在将来中,则会查找承诺。图片将在一秒钟内存在,仍然承诺将返回错误。

我在这里没有得到什么承诺?对我来说,如果图片可用,它看起来像检查的整个未来方面取决于loadImage(url)而不是实际的承诺本身。

PS:受funfunfunction启发的例子

承诺何时解决?

据我所知,它不会“监听”它周围的其他代码,更不用说可能在后台运行的框架了。我会假设在这个例子中它会像这样:承诺检查图片是否可用 - >他们仍然在后台工作 - >承诺解决并抛出错误 - >算法用图片完成 - >图片可用?

1 个答案:

答案 0 :(得分:2)

  

JavaScript中的承诺有什么意义?

请参阅:You're Missing the Point of Promises

无法考虑与单独使用Promise相关的所有细微差别。浏览promise标记,以阅读经常以promise标记发布的用户发布的其他用户的问题和答案。在这些问题和答案的评论中询问有关具体案例的问题,以便进行自己的启发。

使用Promise.then()获得.catch()的值,而不是检查Promise链之外的变量值。

无视“现在”和“未来”。专注于在.then().catch()中实施代码。引用标识符引用的异步值的所有其他代码将不可靠。

let id = void 0;

let promise = new Promise(resolve => 
                setTimeout(() => {id = 123; resolve(id) }, Math.random() * 2000)
              );

// this is not accurate
console.log(`id: ${id}`); // what is `id` here?

promise.then(res => console.log(`id: ${res}`));

另请注意,作为执行程序传递给Promise构造函数的函数会立即调用

let id = void 0;

let promise = new Promise(resolve => 
                setTimeout(resolve, Math.random() * 2000, id = 123)
              );

// is this accurate?
console.log(`id: ${id}`); // what is `id` here?

promise.then(res => console.log(`id: ${res}`));

return来自.then()的值。

return来自.then()的值。使用.map()代替.forEach()

Promise.resolve(123)
.then(data => console.log(data))
.then(res => console.log(res)) // `undefined`

Promise.resolve(123)
.then(data => { console.log(data); return data})
.then(res => console.log(res)) // `123`

使用.map()代替.forEach()

let fn = (id) =>  new Promise(resolve => 
                    setTimeout(resolve, Math.random() * 2000, id)
                  );
                  
Promise.all([1,2,3].map(fn))
.then(data => Promise.all(data.forEach(id => fn(id * 10))))
.then(data => console.log(`data: ${data}`)); // where is `data`

                  
Promise.all([1,2,3].map(fn))
.then(data => Promise.all(data.map(id => fn(id * 10))))
.then(data => console.log(`data: ${data}`)); // `[10, 20, 30]`

已处理的拒绝或错误转换为已解决的Promise不是throw n或拒绝已退回

let fn = () => new Promise((resolve, reject) => 
                setTimeout((id) => {reject(new Error(id)) }, Math.random() * 2000, 123)
              )

fn().then(res => console.log(`id: ${res}`))
.catch(err => console.log(`err: ${err}`))
.then(res => console.log(`res: ${res}`)) // `undefined`

fn().then(res => console.log(`res: ${res}`))
.catch(err => { console.log(`err: ${err}`); return err })
// `.then()` is not called, function passed to `.catch()` is called
.then(res => console.log(`res: ${res}`)) 
.catch(err => console.log(`err: ${err}`)) // `123`