【问题标题】:What is the point of promises in JavaScript?JavaScript 中的 Promise 有什么意义?
【发布时间】:2017-10-14 10:22:35
【问题描述】:

承诺是一个

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

假设我有一个想要处理图片的应用程序。图片已加载,例如在算法在后台使用它(或某种其他类型的延迟)之后。现在我想通过使用承诺而不是回调来检查图片是否在未来中可用。

要检查图像是否可用,我可以使用以下代码:

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

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

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 启发的示例


promise 如何知道它何时被解决?

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

【问题讨论】:

  • “promise 仍然会返回错误。” javascript 的问题在哪里出错?
  • 请注意这是假设性的!我知道还有其他方法可以解决这个问题。我想了解 Promise 在这里如何帮助我,以及为什么一切似乎都取决于 loadImage(url),而不是 Promise 本身
  • 因为如果图片现在可用,promise 会查找,而不是将来。 - 关于未来的事情是它有一个习惯,最终变成现在。
  • You're Missing the Point of PromisesPromise 仅有助于执行任务。使用Promise 并不能免除开发人员在代码中编写和维护正确的逻辑和错误处理的责任。
  • Promise 将返回错误并转到// handle error,因为图像现在不可用。它们将在未来推出。

标签: javascript asynchronous promise es6-promise


【解决方案1】:

JavaScript 中的 Promise 有什么意义?

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


无法考虑与单独使用 Promise 相关的所有细微差别。浏览promise 标签以阅读经常在promise 标签上发帖的用户发布的其他用户的问题和答案。在这些问答中就 cmet 的具体案例提出问题,以供您自己启迪。


您可以使用.then().catch() 获取Promise 的值,而不是通过检查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 不是thrown 或拒绝返回

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`

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 2016-12-09
    • 1970-01-01
    • 2011-01-09
    • 2016-07-04
    • 2018-06-03
    • 2013-06-15
    相关资源
    最近更新 更多