【问题标题】:Javascript (NodeJS) promise pending?Javascript(NodeJS)承诺待定?
【发布时间】:2017-01-01 05:55:39
【问题描述】:
function  f () {
   return new Promise(function (resolve, reject) {

        resolve(4);
    })
}

function  g () {
    return f().then((res) => {return res;})

}

console.log(g());

返回 Promise { <pending> }

如果我返回res(在then中)然后返回f(),为什么输出不是4

【问题讨论】:

  • 如果是返回4,你将如何链接thens?
  • @WiktorZychla?在return f().then((res) => {return res;}) 中,这是否给了4?由于then 返回 4??
  • 然后不返回 4,它返回一个 Promise。您作为参数传递给的函数然后返回 4。

标签: javascript node.js


【解决方案1】:

一个有效的答案是:

function f() {
    return new Promise(function(resolve, reject) {

        resolve(4);
    })
}

function g() {
    return f().then((res) => {
        return res;
    })
    .then((res) =>{
        console.log(res);
    })

}
g()

为什么?任何时候你在一个 Promise 中的 then 语句中 return 时,它都会将它传递给下一个语句(then 或 catch)。尝试注释掉return res,你会看到它打印出undefined

==============
但是,在 ES7 中,我们可以使用 async/await。我们可以使用以下代码复制上述内容:

function f() {
  return new Promise(function(resolve, reject) {
    resolve(4);
  });
}

async function g() {
  var a = await f();
  // do something with a ...
  console.log(a);
}

g();

重要的是要注意console.log(g()) 仍然返回一个承诺。这是因为在实际的函数 g 中,解析 promise 会延迟,因此不会阻止我们的其余代码执行,但函数体可以利用来自 f 的返回值。

注意:要运行它,您需要节点 7,并且应该使用 --harmony-async-await 选项执行它。

============
编辑以包含新代码 sn-p
看下面的代码。您必须使用 then 来访问以前的对象 - 但是,在这种情况下,您在哪里访问它取决于您。您可以在 Promise.all 内的每个 promise 上调用 then,在本例中为 .then((userVictories) => ...).then(...) 或一旦 Promise.all 返回。需要注意的是,Promise.all 一旦 all 承诺它包含解析,就会返回。

var membersArray = groupFound.members;
Promise.all(membersArray.map((member) => {
  return db.doneTodo.find({ 'victor._id': member._id }).then((userVictories) => {
    return {
      email: member.email,
      victories: userVictories.length,
    }
  }).then(obj => {
    /*
        obj is each object with the signature:
            {email: '', victories: ''}

            calling this then is optional if you want to process each object
            returned from '.then((userVictories) =>)'

            NOTE: this statement is processed then *this* promise resolves

            We can send an email to each user with an update
     */
  });
}))
  .then((arr) => {
    /*
        arr is an array of all previous promises in this case:
        [{email: '', victories: ''}, {email: '', victories: ''}, ...]

        NOTE: this statement is processed when all of the promises above resolve.

        We can use the array to get the sum of all victories or the 
        user with the most victories
     */
  })

【讨论】:

  • 但是这里:var membersArray = groupFound.members; Promise.all(membersArray.map((member) => { return db .doneTodo .find({'victor._id': member._id}) .then((userVictories) => { return { email: member.email, victories: userVictories.length } }); }))我们不需要在对象前面附加一个“then”吗?
  • '我们不需要在对象前面附加一个“then”吗?',哪个对象? db.doneTodo.find 返回一个承诺,之后您调用 .then((userVictories) => ...。我不完全理解你的评论
  • 最后一个带有“email”和“victories...”的对象
  • membersArray 我假设是一组具有 email 和 id 属性的对象 ({email: 'test@test.com', id:1})。通过调用 map,您可以遍历每个成员并调用 db.doneTodo.find 来解决一个承诺。在您的 then 块内 .then((userVictories) => ...) 您处理它的结果。一旦数组中的所有 Promise 解析完毕,Promise.all 将返回,因此它最终成为对象数组{email: ..., victories: ...}。为了访问这些对象,您需要像这样调用Promise.all(...).then(arr => console.log(res);)
  • var a = Promise.all(...)console.log(a) 它应该打印一个承诺
【解决方案2】:

让我们先看看 jQuery 作为学习 Promise 的介绍。

此代码返回什么? result的值是多少?

var result = $('body');

提示:它不会是<body/> body HTML 元素。

result 是一个 jQuery 集合对象。在内部,它包含对 body 标记的引用。但实际的result 对象是一个集合。

这会返回什么?

var result = $('body').css('background', 'red');

同样,它返回一个 jQuery 集合。

还有这个?

var result = $('body').css('background', 'red').animate({height: "20px"});

同样的事情。一个 jQuery 集合。

现在,这个基于承诺的代码返回什么?

var result = new Promise();

很明显这会返回一个承诺。但是这段代码呢?

var result = new Promise().resolve().then(() => {
    return 'Hello';
});

result 现在的值是多少?提示:这不是字符串'Hello'

这是一个承诺!

这会返回什么?

var result = new Promise().resolve().then(() => {
    return new Promise().resolve();
}).then(() => {
    return 'Hello';
}).catch(() => {
    console.log('Something went wrong');
});

它返回一个承诺! Promise 让我们可以访问稍后调用的函数中的值。在执行该函数之前,您将无法访问承诺“返回”或“解决”的任何内容。进入承诺链后,您始终必须使用.then(fn) 来处理程序流程中的下一步。

Javascript 是异步的。所有顶级代码都按顺序执行而不会暂停。在您的console.log 完成执行很久之后,promise 将在稍后解决。要恢复价值,您需要留在承诺链领域:

g().then( result => console.log(result) );

【讨论】:

  • 谢谢!但是这里会发生什么:Promise.all(membersArray.map((member) => { return db ///NEED THE RETURN HERE .doneTodo .find({'victor._id': member._id}) .then((userVictories) => { return { email: member.email, victories: userVictories.length } }); })).then( (res) => console.log(res)) ?
  • { return { email: member.email, victories: userVictories.length }之后什么都没有
  • 在 Promise.all 之后的链式 .then() 将是一个数组,其中包含每个已解决的 Promise developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 的值
  • 您的代码表面上看起来不错。尝试在末尾添加一个 catch 以查看是否有错误 gist.github.com/AndrewRayCode/6495e7c0dc0f2370184c90ead7a528ea
  • 如何解决一个承诺? { return { email: member.email, victories: userVictories.length } 是否解决了承诺?
猜你喜欢
  • 2020-08-19
  • 2022-11-26
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2018-08-27
相关资源
最近更新 更多