相关疑难解决方法(0)

在Javascript中通过一系列承诺传递状态有哪些模式?

我正在尝试学习一些关于Node和异步编程的知识.我读到了Promises,并试图在一个小项目中使用它们,这个项目将用户的帖子从服务A复制到服务B.我在理解如何最好地在Promises之间传递状态时遇到一些麻烦

该项目是使用Promise库为NodeJS编写的

我当前问题的一个简单定义是:

  • 如果服务B中尚不存在帖子,则将用户的帖子从服务A复制到服务B.
  • 这两种服务都提供http API,需要一个不易记忆的用户ID来查找该用户的帖子,因此必须从用户名中查找用户ID.
  • 所有的http调用都是异步的.

这是一些伪代码,说明了我如何将Promise链接在一起.

Promise.from('service_A_username')
  .then(getServiceAUserIdForUsername)
  .then(getServiceAPostsForUserId)
  .then(function(serviceAPosts) {
    // but what? store globally for access later?
    doSomethingWith(serviceAPosts);
    return Promise.from('service_B_username');
  })
  .then(getServiceBUserIdForUsername)
  .then(getServiceBPostsForUserId)
  .done(function(serviceBPosts) {
    // how do we interact with Service A posts?
    doSomethingThatInvolvesServiceAPostsWith(serviceBPosts); 
  });
Run Code Online (Sandbox Code Playgroud)

我想过要做的一些事情:

  1. 将getIdForUsername调用带入getPostsForUserId函数.但是,我希望保持每个功能单元尽可能简单,遵循"做一件事,做得好"的原则.
  2. 创建一个"上下文"对象并将其传递给整个链,在此对象中读取和存储状态.然而,这种方法使得每个功能都非常适用于链条,因此难以单独使用.

还有其他选择,建议采用什么方法?

javascript asynchronous chaining node.js promise

9
推荐指数
2
解决办法
1353
查看次数

ES6 Promises和PEP3148期货的链接差异

我对ES6 Promises和PEP3148期货的实施差异进行推理有点困惑.在Javascript中,当Promise与另一个Promise一起解决时,"outer"promise会在解决或拒绝后继承"内部"promise的值.在Python中,"外部"的未来会立即用"内在的"未来来解决,而不是它的最终价值,这就是问题所在.

为了说明这一点,我为两个平台提供了两个代码片段.在Python中,代码如下所示:

import asyncio

async def foo():
    return asyncio.sleep(delay=2, result=42)

async def bar():
    return foo()

async def main():
    print(await bar())

asyncio.get_event_loop().run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)

在Javascript中,完全等效的代码是这样的:

function sleep(delay, result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(result);
        }, delay * 1000);
    });
}

async function foo() {
    return sleep(2, 42);
}

async function bar() {
    return foo();
}

(async function main() {
    console.log(await bar());
})();
Run Code Online (Sandbox Code Playgroud)

sleep 为完整起见而提供的功能.

42正如预期的那样打印Javascript代码.Python代码打印<coroutine object foo at 0x102a05678>和关于"coroutine'foo'的投诉从未等待过".

通过这种方式,JS允许您选择控制将在当前执行上下文中消失的时间点,立即执行awaitpromises,或让调用者等待它们.Python总是让你没有其他选择,而不是总是awaitFuture/coroutine,因为否则你将不得不用一个丑陋的包装器函数在循环中展开Future链,如下所示: …

javascript python future promise async-await

7
推荐指数
1
解决办法
532
查看次数

访问先前履行的承诺会导致承诺链

在使用promises进行编码时,在一系列承诺中访问很久以前的数据是正确的模式是什么?

例如:

do_A.then(do_B).then(do_C).then(do_D).then(do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_IsSuccesfullyCompleted)
Run Code Online (Sandbox Code Playgroud)

我目前的解决方案:通过链路传递单个JSON结构,并让每个步骤填充它.有什么意见吗?

javascript promise

6
推荐指数
1
解决办法
244
查看次数

node.js链多个promises(用mongoose)

以下是我正在处理的典型承诺函数.

var _delete = function(t, id) { 
  return Promise.cast(Event.find({where: {id: id}}, {transaction: t}))
  .then(function(d){
    if (d) {
      // ------- (*)
      return Promise.cast(d.updateAttributes({status: -1}, {transaction: t}))
      .then(function(){
          // do inventory stuff 
          return Promise.cast(Inventory.update({}).exec())
          .then(function(d){
               // do something 
          })
      }).then(function(){
          // do product stuff
          return Promise.cast(Product.update({}).exec())
          .then(function(d){
               // do something 
          })
      })
    } else {
      return Promise.reject('this transaction list does not exist');
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

这看起来不错,直到我处理更复杂的更新/创建代码将变得非常混乱.

目前我正在做的承诺是1.我有很多无用的返回真实语句,唯一的目的是转到下一个.然后声明2. promise以嵌套方式编程.输入参数通常很复杂,并且有超过1个参数,所以我不能做这样的事情

.then(fun1).then(fun2)

......等

这使我无法'tap'使用.then语句启用/禁用功能.

所以我的问题是如何正确地做到这一点?谢谢..


以下是我所说的非常丑陋的事情....

var _process = function(t, tid) …
Run Code Online (Sandbox Code Playgroud)

javascript node.js promise bluebird

6
推荐指数
1
解决办法
1万
查看次数

Javascript承诺序列

我想在序列中处理许多承诺.我在下面有一段工作代码,但我想知道我是否过度复杂了承诺的链接.我似乎正在创造大量新的封闭装置,我想知道我是否遗漏了一些东西.

有没有更好的方法来编写此函数:

'use strict';
addElement("first")
.then(x => {return addElement("second")})
.then(x => { return addElement("third")})
.then(x => { return addElement("fourth")})   

function addElement(elementText){
    var myPromise = new Promise(function(resolve,reject){
        setTimeout(function(){
            var element=document.createElement('H1');
            element.innerText = `${elementText} ${Date.now()}`;
            document.body.appendChild(element);
            resolve();
        }, Math.random() * 2000);
    });
return myPromise;
}
Run Code Online (Sandbox Code Playgroud)

javascript promise ecmascript-6

6
推荐指数
2
解决办法
1860
查看次数

如何正确链接Promise与嵌套

我的节点项目当前包含一个嵌套的回调圣诞树,以便获取数据并按正确的顺序处理它们.现在我正在尝试使用Promises重构,但我不确定如何正确地执行它.

假设我正在提取办公室列表,然后为每个办公室提供所有员工,然后是每个员工的工资.最后,所有实体(办公室,员工和工资)应链接在一起并存储在数据库中.

一些伪代码说明了我当前的代码(省略了错误处理):

fetch(officesEndpoint, function (data, response) {
    parse(data, function (err, offices) {
        offices.forEach(function (office) {
            save(office);
            fetch(employeesEndPoint, function (data, response) {
                parse(data, function (err, employees) {
                    // link each employee to office
                    save(office);
                    save(employee);
                    employees.forEach(function () {
                        fetch(salaryEndpoint, function (data, response) {
                            parse(data, function (err, salaries) {
                                // link salary to employee
                                save(employee);
                            });
                        });
                    });
                });
            });
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

我尝试用承诺解决这个问题,但我有几个问题:

  • 那种冗长?
  • 每个办公室都需要与他们各自的员工联系,但在这个saveEmployees职能中,我只能访问员工,而不是办公室中的其他办公室:

var restClient = require('node-rest-client');
var client = new restClient.Client();
var xml2js = require('xml2js'); …
Run Code Online (Sandbox Code Playgroud)

javascript node.js promise

6
推荐指数
1
解决办法
196
查看次数

如何在没有"缩进金字塔"的情况下正确表达任意Promise链?

有一些方法,如Q.reduceQ.all这有助于展平诺言的异类集合的特定情况下诺言链.但请注意,通用案例:

const F = (x) => x;
const a = F(1);
const b = F(2);
const c = F(a + b);
const d = F(a + c);
const e = F(b + c);
console.log(e); 
Run Code Online (Sandbox Code Playgroud)

也就是说,每个术语依赖于任意先前定义的术语的一系列赋值.假设这F是一个异步调用:

const F = (x) => Q.delay(1000).return(x);
Run Code Online (Sandbox Code Playgroud)

在没有生成缩进金字塔的情况下,我无法想到表达该模式:

F(100).then(a =>
  F(200).then(b =>
    F(a+b).then(c =>
      F(a+c).then(d =>
        F(b+c).then(e =>
          F(d+e).then(f =>
            console.log(f)
          )
        )
      )
    )
  )
);
Run Code Online (Sandbox Code Playgroud)

请注意,使用返回的值不起作用:

F(100).then(a => F(200))
    .then(b => F(a+b))
    .then(c => F(a+c))
    .then(d => F(b+c)) …
Run Code Online (Sandbox Code Playgroud)

javascript promise bluebird

6
推荐指数
1
解决办法
451
查看次数

不定义变量名的JS对象解构

在 ES6 JS 中解构对象时,您可以使用{ a, b }语法从该对象创建新变量,分别调用ab。但是,据我所知,无法获取对象的键以自动创建具有这些名称的本地范围变量。在下面的例子中,我希望能够使用的假设的伪代码const {} = args;,它会产生const aconst b自动。

const bar = { a: 'apple', b: 'ball' };

const foo = (args) => {
  const { a, b } = args;
  console.log(a, b); // Great!
  const {} = args;   // I am aware this isn't valid syntax...
  console.log(a, b)  // Because of course, it doesn't work.
};

foo(bar);
Run Code Online (Sandbox Code Playgroud)

原因纯粹是因为,在这个 MCVE 之外,我实际上使用了一个带有数十个键的大型对象,我想将其中的某些值传递到 Promise 链的下一部分。我当然可以使用 …

javascript ecmascript-6 object-destructuring

6
推荐指数
1
解决办法
987
查看次数

减少 cypress 中的回调嵌套

我读到在 Cypress 中我不应该使用它await,也不需要它,因为您可以通过链接删除嵌套。这里我有一个cy.fixure嵌套 incy.origin嵌套 in cy.session,有没有办法把它展平?

  cy.session([], () => {
    cy.visit("")
    cy.origin("https://my-address.com", () => {
      cy.fixture("user").then((user) => {
        cy.get("#username").type(user.username)
        cy.get("#password").type(user.password)
      })

      cy.get("button[type='submit']").click()
      cy.url().should("equal", "/login-success")
    })
  })
Run Code Online (Sandbox Code Playgroud)

编辑
这不是关于常规 javascript 的问题,它是Cypress特定的,正常的 async/await 在这里不起作用。

javascript cypress cypress-origin

6
推荐指数
1
解决办法
225
查看次数

了解产量/生成器的代码流

我已经阅读了几个使用JavaScript生成器的代码示例,例如这个.我能想到的最简单的生成器使用块是这样的:

function read(path) {
    return function (done) {
        fs.readFile(path, "file", done);
    }
}

co(function *() {
    console.log( yield read("file") );
})();
Run Code Online (Sandbox Code Playgroud)

这确实打印出了内容file,但我的挂断是在哪里done调用.看起来,yield是一个语法糖,用于包装它在回调中返回的内容并适当地分配结果值(至少在co将错误参数抛给回调的情况下).我对语法的理解是否正确?

使用done时看起来像什么yield

javascript yield generator node.js co

5
推荐指数
1
解决办法
1881
查看次数