Promise 在这种情况下如何执行?

Posted

技术标签:

【中文标题】Promise 在这种情况下如何执行?【英文标题】:Promise how to implement in this situation? 【发布时间】:2016-07-27 15:26:14 【问题描述】:

我在使用 fs.readfile 进行同步时遇到问题,它们第一次没有初始化,如果我再次尝试请求,那么我有结果。我知道我可以使用 Promise,并且我发现 Q from Kriskowal 有一些有用的东西。 我试过但没有成功。我不太了解如何实现它。如果有人可以帮助解决这个问题,我将永远感激不尽。

代码:

  "use strict"

 var Q = require('q');
 var fs = require('fs');
 var arrayZipBand = [];
 var jsonZipCode = [];
 var arrayParsedZipcodeBr = [];

 exports.parse = function(opts) 

if (opts.zipBand.constructor != Array) 
opts.zipBand = [opts.zipBand];

if (opts.location.constructor != Array) 
opts.location = [opts.location];


if (opts.config === 0) 
opts.zipBand.forEach(function(file) 
  fs.readFile(file, 'utf8', function(err, logData) 
    if (err) throw err;
    let text = logData.toString();
    decodeURIComponent(text);

    let lines = text.split('\n');

    lines.forEach(function(line) 
      let parts = line.split('@');

      if (parts[1] != undefined) 
        let obJson = 
          LOC_NU: parts[0],
          LOC_CEP_INI: parts[1],
          LOC_CEP_FIM: parts[2]

        
        arrayZipBand.push(obJson);
      

    );


  );

);

opts.location.forEach(function(file) 
  fs.readFile(file, 'utf8', function(err, logData) 


    if (err) throw err;

    let text = logData.toString();
    decodeURIComponent(text);

    let lines = text.split('\n');

    lines.forEach(function(line) 
      let parts = line.split('@');

      if (parts[1] != undefined) 
        for (let i = 0; i < arrayZipBand.length; i++) 
          if (parts[0] == arrayZipBand[i].LOC_NU) 
            jsonZipCode.push(arrayZipBand[i]);
          
        
        if (jsonZipCode === undefined) 
          throw "Was not possible to find Zipcode for the id " + parts[0];
        

        for (let i = 0; i < jsonZipCode.length; i++) 
          let obJson = 
            LOC_NU: parts[0],
            UFE_SG: parts[1],
            LOC_NO: parts[2],
            MUN_NU: parts[8],
            LOC_CEP_INI: jsonZipCode[i].LOC_CEP_INI,
            LOC_CEP_FIM: jsonZipCode[i].LOC_CEP_FIM
          

          arrayParsedZipcodeBr.push(obJson);
        
        jsonZipCode = [];

      


    );
  );
);



;
 return arrayParsedZipcodeBr;


【问题讨论】:

npmjs.com/package/promise-denodeify 那么,您是如何尝试使用 Promise 的?请edit您的问题向我们展示您的尝试。你读过 Q 文档吗?您是否看到使用 Q 辅助函数调用 fs 方法以便从它们那里获得承诺的示例? 【参考方案1】:

嗯,您似乎正在尝试在循环周期中读取文件,但是以异步方式。第一个问题,为什么要异步读取这些文件?您可以随时同步阅读它们:

var data=fs.readFileSync(fname, encoding);

顺便说一句,如果您希望异步读取它们并保持 for...循环,您需要类似 Promise、定时等待或更复杂的同步机制。

您可以保持简单,而无需以这种方式使用任何其他包/模块:

/**
       * Promise.All
       * @param items Array of objects
       * @param block Function block(item,index,resolve,reject)
       * @param done Function Success block
       * @param fail Function Failure block
       * @example

          promiseAll(["a","b","c"],
          function(item,index,resolve,reject) 
            MyApp.call(item,function(result) 
              resolve(result);
            ,
            function( error )  reject(error); ):
          ,
          function(result)  // aggregated results

          ,function(error)  // error

          )

        * @author Loreto Parisi (loretoparisi at gmail dot com)
       */
    promiseAll: function(items, block, done, fail) 
            var self = this;
            var promises = [],
                index = 0;
            items.forEach(function(item) 
                promises.push(function(item, i) 
                    return new Promise(function(resolve, reject) 
                        if (block) 
                            block.apply(this, [item, index, resolve, reject]);
                        
                    );
                (item, ++index))
            );
            Promise.all(promises).then(function AcceptHandler(results) 
                if (done) done(results);
            , function ErrorHandler(error) 
                if (fail) fail(error);
            );
        , //promiseAll

所以你可以这样称呼它

promiseAll(arrayOfItems, function(item, index, resolve, reject) 
    // do something on item
    if (someSuccessCondOnThisItem) 
        resolve(item)
     else 
        reject(new Error("operation failed"))
    
, function(results)  // aggregated results

    console.log("All done %d", results.length);

, function(error)  // error
    console.log(error.toString());
);

请记住,这是一种非常简单的方法,但在大多数情况下,它在循环遍历数组时有效。

这是操场上的一个简单的工作示例:

var console = 
 log : function(s)  document.getElementById("console").innerhtml+=s+"<br/>"

var promiseAll= function(items, block, done, fail) 
            var self = this;
            var promises = [],
                index = 0;
            items.forEach(function(item) 
                promises.push(function(item, i) 
                    return new Promise(function(resolve, reject) 
                        if (block) 
                            block.apply(this, [item, index, resolve, reject]);
                        
                    );
                (item, ++index))
            );
            Promise.all(promises).then(function AcceptHandler(results) 
                if (done) done(results);
            , function ErrorHandler(error) 
                if (fail) fail(error);
            );
        ; //promiseAll

arr=[1,2,3]
promiseAll(arr
                ,function(item,index,resolve,reject) 
                  console.log("Resolving item[" + index+"]")
                  var okCond=true
                  if(okCond) resolve(item) else  reject(new Error("item[" + index+"]")) 
                
                ,function(results)  // aggregated results
console.log("All done of "+results.length);
                
                ,function(error)  // error
                console.log(error);
 );
&lt;div id="console"/&gt;

最后,一个完整的异步示例,展示了在循环遍历列表时如何延迟 XMLHttpRequest 的执行。 ExecutionBlock 在 SimpleRequest 响应后调用 rejectresolve,导致 Promise 在调用 then 之前等待其执行。

var console = 
    log: function(s) 
      document.getElementById("console").innerHTML += s + "<br/>"
    
  
  // Simple XMLHttpRequest
  // based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = 
    call: function(what, response) 
      var request;
      if (window.XMLHttpRequest)  // Mozilla, Safari, ...
        request = new XMLHttpRequest();
       else if (window.ActiveXObject)  // IE
        try 
          request = new ActiveXObject('Msxml2.XMLHTTP');
         catch (e) 
          try 
            request = new ActiveXObject('Microsoft.XMLHTTP');
           catch (e) 
        
      
      // state changes
      request.onreadystatechange = function() 
        if (request.readyState === 4)  // done
          if (request.status === 200)  // complete	
            response(request.responseText)
           else response();
        
      
      request.open('GET', what, true);
      request.send(null);
    
  
  //PromiseAll
var promiseAll = function(items, block, done, fail) 
  var self = this;
  var promises = [],
    index = 0;
  items.forEach(function(item) 
    promises.push(function(item, i) 
      return new Promise(function(resolve, reject) 
        if (block) 
          block.apply(this, [item, index, resolve, reject]);
        
      );
    (item, ++index))
  );
  Promise.all(promises).then(function AcceptHandler(results) 
    if (done) done(results);
  , function ErrorHandler(error) 
    if (fail) fail(error);
  );
; //promiseAll

// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) 
  SimpleRequest.call('https://icanhazip.com/', function(result) 
    if (result) 
      console.log("Response[" + index + "] " + result);
      resolve(result);
     else 
      reject(new Error("call error"));
    
  )


arr = [1, 2, 3]
promiseAll(arr, function(item, index, resolve, reject) 
  console.log("Making request [" + index + "]")
  ExecutionBlock(item, index, resolve, reject);
, function(results)  // aggregated results
  console.log("All response received " + results.length);
  console.log(JSON.stringify(results));
, function(error)  // error
  console.log(error);
);
&lt;div id="console" /&gt;

【讨论】:

@michelpm1 不客气,也许你可以编辑标题,比如promise all in for循环等。最后一个例子,展示了如何将数组作为XMLHttpRequest减少到web网站网址...

以上是关于Promise 在这种情况下如何执行?的主要内容,如果未能解决你的问题,请参考以下文章

promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

ES6 promise

asyncawait与Promise

ES6新特性:Javascript中内置的延迟对象Promise

Promise探究

Promise如何使用?全方位解析,5分钟搞懂异步#yyds干货盘点#